Вот один из способов сделать это, который также оказывается очень эффективным, если у вас очень большие списки:
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
Эта функция (обработчик), как следует из ее названия, берет список ифильтрует его по некоторому критерию.Затем он дополнительно сохраняет отфильтрованные элементы в новом списке, который можно передать в обработчик для заполнения;или вы можете разрешить обработчику возвращать отфильтрованный список как его результат, а затем присвоить его новой переменной.
Фильтр предоставляется с помощью другого обработчика, который вы определяете.Это функция, которая воздействует на каждый элемент списка и возвращает 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"}}
РЕДАКТИРОВАТЬ: Обработка нескольких похожих случаев
* 1032Что делать, если у меня много повторяющихся первых значений?Я должен создать обработчики для каждого из них?
Нет, но нам нужно немного подкорректировать обработчик 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"}}