Applescript比较同一数组中的项目

时间:2018-10-10 11:35:36

标签: arrays list object applescript

我有这个清单

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 个答案:

答案 0 :(得分:1)

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

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

顾名思义,此函数(处理程序)采用一个列表,并根据某些条件对其进行过滤。然后,有选择地将过滤后的项目存储在新列表中,您可以将其传递到要填充的处理程序中。或者您可以允许处理程序返回过滤列表作为其结果,然后将其分配给新变量。

过滤器是通过您定义的另一个处理程序提供的。该函数作用于列表的每个元素,根据其是否通过您定义的某些测试而返回truefalse

在您的特定情况下,您希望其通过的测试是每个项目的第一个元素是特定值,例如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)行。我们正在引入一个辅助函数,将我们的过滤器处理程序嵌套在脚本对象中。 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"}}