代码之家  ›  专栏  ›  技术社区  ›  Spy

Applescript比较同一数组中的项

  •  0
  • Spy  · 技术社区  · 6 年前

    set myList to {{1, "Bob"}, {1.5, "Jane"}, {3, "Joe"}, {1, "Jack"}}
    
    repeat with a in myList
        --something like that a+
        if item 1 of a is equal to item 1 of a+ then
            --create list 
        end if
    end repeat
    

    有没有办法根据第一个属性来比较项目?我想添加到一个列表的所有项目,他们的第一个项目是相同的

    1 回复  |  直到 6 年前
        1
  •  1
  •   Community CDub    4 年前

    这里有一种方法,如果你有非常大的列表,这也是一种非常有效的方法:

    to filterItems from (L as list) ¬
        into |L*| as list : null ¬
        thru filter as handler
        local L, |L*|, filter
        
        if |L*| = null then set |L*| to {}
        
        script filteredItems
            property array : L
            property fn : filter
            property list : |L*|
        end script
        
        tell the filteredItems to repeat with x in its array
            if fn(x) = true then set ¬
                end of its list ¬
                to x's contents
        end repeat
        
        return the list of filteredItems
    end filterItems
    

    顾名思义,这个函数(handler)接受一个列表,并根据某种标准对其进行过滤。然后它选择性地将过滤后的项目存储在一个新的列表中,您可以将该列表传递到要填充的处理程序中;或者您可以允许处理程序返回筛选列表作为其结果,然后将其分配给一个新变量。

    true false 取决于它是否通过了您定义的测试。

    在您的特定情况下,您希望它通过的测试是每个项的第一个元素是一个特定的值,例如1。这样,您就得到了一个筛选列表,其中包含具有匹配的第一个元素的项。

    on firstItemEquals1(x)
        item 1 of x = 1
    end firstItemEquals1
    

    一个简单的单行测试,确保每个项目的第一个元素是1。

    然后,运行以下行时:

    filterItems from myList thru firstItemEquals1
    

    {{1, "Bob"}, {1, "Jack"}}
    

    相反,我们可以定义另一个过滤器处理程序,只挑选第一个元素为奇数的项目;或者第二个元素以字母“J”开头:

    on firstItemIsOdd(x)
        (item 1 of x) mod 2 = 1
    end firstItemIsOdd
    
    
    on secondItemStartsWithJ(x)
        item 2 of x starts with "J"
    end secondItemStartsWithJ
    

    然后:

    filterItems from myList thru firstItemIsOdd
        --> {{1, "Bob"}, {3, "Joe"}, {1, "Jack"}}
    
    
    filterItems from myList thru secondItemStartsWithJ
        --> {{1.5, "Jane"}, {3, "Joe"}, {1, "Jack"}}
    

    编辑:处理多起类似案件

    如果我有很多重复的第一个值呢?我必须为它们中的每一个创建处理程序?

    不,但是我们必须对价格做一个小小的调整 filterItems

    to filterItems from (L as list) ¬
        into |L*| as list : null ¬
        thru filter
        local L, |L*|, filter
        
        if |L*| = null then set |L*| to {}
        
        script itemsToBeFiltered
            property array : L
        end script
        script filteredItems
            property list : |L*|
        end script
        
        repeat with x in the array of itemsToBeFiltered
            tell wrapper(filter) to if fn(x) = true ¬
                then set end of filteredItems's list ¬
                to contents of x
        end repeat
        
        return the list of filteredItems
    end filterItems
    

    意义的主要变化是引入了 tell wrapper(filter) 线路。我们引入了一个helper函数来将过滤器处理程序嵌套在脚本对象中。这个 wrapper

    on wrapper(function)
        if function's class = script then return function
        
        script
            property fn : function
        end script
    end wrapper
    

    现在 ,我们可以定义如下所示的筛选器处理程序:

    on firstItemEquals(N)
        script
            on fn(x)
                item 1 of x = N
            end fn
        end script
    end firstItemEquals
    

    filterItems from myList thru firstItemEquals(1)
        --> {{1, "Bob"}, {1, "Jack"}}
    

    然后这个:

    filterItems from myList thru firstItemEquals(3)
        --> {{3, "Joe"}}