Applescript 比较同一数组中的项目
Applescript compare items in the same array
我有这个列表
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
有没有办法根据第一个 属性 来比较这些项目?我想将第一项相同的所有项目添加到列表中
这是一种方法,如果列表非常大,这也是一种非常有效的方法:
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
这个函数(处理程序),顾名思义,获取一个列表并根据某种标准对其进行过滤。然后,它可以选择将过滤后的项目存储在一个新列表中,您可以将该列表传递给要填充的处理程序;或者您可以允许处理程序将 return 筛选列表作为结果,然后将其分配给新变量。
过滤器是通过您定义的另一个处理程序提供的。这是一个作用于列表中每个元素的函数,returning 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"}}
编辑:处理多个相似案例
what if I have a lot of duplicate first values? I have to create handlers for each one of them ?
不,但我们确实需要对 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"}}
我有这个列表
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
有没有办法根据第一个 属性 来比较这些项目?我想将第一项相同的所有项目添加到列表中
这是一种方法,如果列表非常大,这也是一种非常有效的方法:
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
这个函数(处理程序),顾名思义,获取一个列表并根据某种标准对其进行过滤。然后,它可以选择将过滤后的项目存储在一个新列表中,您可以将该列表传递给要填充的处理程序;或者您可以允许处理程序将 return 筛选列表作为结果,然后将其分配给新变量。
过滤器是通过您定义的另一个处理程序提供的。这是一个作用于列表中每个元素的函数,returning 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"}}
编辑:处理多个相似案例
what if I have a lot of duplicate first values? I have to create handlers for each one of them ?
不,但我们确实需要对 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"}}