Инструменты итератора, или сокращенно itertools , представляют собой набор удобных инструментов для обработки последовательностей данных, таких как массивы, итераторы и строки. Некоторые имена и API основаны на Python itertools .
Примеры
Общие операции включают в себя:
map и mapByfilter , differencesortedgroupByaccumulate , collapse и reduce Чтобы использовать доступные фильтры/функции itertools через Twig, просто добавьте это определение службы в свой config/services.yaml
Zicht itertools twigExtension :
tags : ['twig.extension'] composer testcomposer lint В приведенных ниже примерах будут использоваться следующие данные, чтобы проиллюстрировать, как работают различные инструменты Iterator:
$ words = [ ' Useful ' , ' Goonies ' , ' oven ' , ' Bland ' , ' notorious ' ];
$ numbers = [ 1 , 3 , 2 , 5 , 4 ];
$ vehicles = [
[
' id ' => 1 ,
' type ' => ' car ' ,
' wheels ' => 4 ,
' colors ' => [ ' red ' , ' green ' , ' blue ' ],
' is_cool ' => false ,
' price ' => 20000 ,
],
[
' id ' => 2 ,
' type ' => ' bike ' ,
' wheels ' => 2 ,
' colors ' => [ ' red ' , ' green ' , ' blue ' ],
' is_cool ' => false ,
' price ' => 600 ,
],
[
' id ' => 5 ,
' type ' => ' unicicle ' ,
' wheels ' => 1 ,
' colors ' => [ ' red ' ],
' is_cool ' => true ,
' price ' => 150 ,
],
[
' id ' => 9 ,
' type ' => ' car ' ,
' wheels ' => 8 ,
' colors ' => [ ' blue ' ],
' is_cool ' => true ,
' price ' => 100000 ,
],
];Используя приведенный выше пример данных, вы можете использовать itertools , чтобы получить все уникальные цвета автомобилей в алфавитном порядке:
use Zicht itertools util Filters ;
use function Zicht itertools iterable ;
$ vehicles = iterable ( $ vehicles )
-> filter (Filters:: equals ( ' car ' , ' type ' )) // {[vehicle...], [vehicle...]}
-> map ( ' colors ' ) // {0: ['red', 'green', 'blue'], 1: ['blue']}
-> collapse () // {0: 'red', 1: 'green', 2: 'blue', 3: 'blue'}
-> unique () // {0: 'red', 1: 'green', 2: 'blue'}
-> sorted (); // {2: 'blue', 1: 'green', 0: 'red'}Вы можете добиться того же в Twig:
{% for vehicle_color in vehicles
|it. filter ( it . filters . equals ( ' car ' , ' type ' ))
|it. map ( ' colors ' )
|it. collapse
|it. unique
|it. sorted
%}
{{ vehicle_color }}
{% endfor %} Многим itertools можно передать параметр $strategy . Этот параметр используется для получения значения из элементов коллекции. $strategy может быть одним из трех:
null, и в этом случае возвращается сам элемент. Например:
use function Zicht itertools iterable ;
$ result = iterable ( $ words )-> map ( null );
var_dump ( $ result );
// {0: 'Useful', 1: 'Goonies', 2: 'oven', 3: 'Bland', 4: 'notorious'}Или в Twig:
{{ dump ( word |it. map ) }}замыкание, и в этом случае замыкание вызывается со значением элемента и ключом в качестве параметров, которые будут использоваться для вычисления возвращаемого значения. Например:
use function Zicht itertools iterable ;
$ getDouble = fn ( $ value , $ key ) => 2 * $ value ;
$ result = iterable ( $ numbers )-> map ( $ getDouble );
var_dump ( $ result );
// {0: 2, 1: 6, 2: 4, 3: 10, 4: 8}Или в Twig:
{{ dump ( numbers |it. map ( num => 2 * num )) }}строка, и в этом случае эта строка используется для создания замыкания, которое пытается найти общедоступные свойства, методы или индексы массива. Например:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> map ( ' type ' );
var_dump ( $ result );
// {0: 'car', 1: 'bike', 2: 'unicicle', 3: 'car'}Или в Twig:
{{ dump ( word |it. map ) }}Строка может состоять из нескольких слов, разделенных точками, что обеспечивает доступ к вложенным свойствам, методам и индексам массива.
Если одно из слов в строке невозможно преобразовать в существующее свойство, метод или индекс массива, будет возвращено значение null . Например:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> map ( ' colors.2 ' );
var_dump ( $ result );
// {0: 'blue', 1: 'blue', 2: null, 3: null}Или в Twig:
{{ dump ( vehicles |it. map ( ' colors.2 ' )) }} Один из способов использования инструментов Iterator — преобразовать массив, Iterator, строку и т. д. в IterableIterator . Этот класс обеспечивает удобный интерфейс для всех распространенных операций. Например:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> filter ( ' is_cool ' )-> mapBy ( ' id ' )-> map ( ' type ' );
var_dump ( $ result );
// {5: 'unicicle', 9: 'car'}Или в Twig:
{{ dump ( vehicles |it. filter ( ' is_cool ' ).mapBy( ' id ' ).map( ' type ' )) }} Сопоставление преобразует одну коллекцию в другую коллекцию равной длины. Использование map позволяет манипулировать элементами, а mapBy позволяет манипулировать ключами коллекции.
Например, мы можем использовать замыкание для создания заголовка для каждого элемента в $vehicles :
use function Zicht itertools iterable ;
$ getTitle = fn ( $ value , $ key ) => sprintf ( ' %s with %s wheels ' , $ value [ ' type ' ], $ value [ ' wheels ' ]);
$ titles = iterable ( $ vehicles )-> map ( $ getTitle );
var_dump ( $ titles );
// {0: 'car with 4 wheels', ..., 3: 'car with 8 wheels'} Используя стратегию получения строк, мы можем легко получить типы для каждого элемента в $vehicles сопоставленные с идентификаторами транспортных средств. Например:
use function Zicht itertools iterable ;
$ types = iterable ( $ vehicles )-> mapBy ( ' id ' )-> map ( ' type ' );
var_dump ( $ types );
// {1: 'car', 2: 'bike', 5: 'unicicle', 9: 'car'}Или в Twig:
{{ dump ( vehicles |it. mapBy ( ' id ' ).map( ' type ' )) }} В Mappings.php доступно несколько распространенных замыканий сопоставления. Вызов этих функций возвращает замыкание, которое можно передать в map и mapBy . Например:
use Zicht itertools util Mappings ;
use function Zicht itertools iterable ;
$ lengths = iterable ( $ words )-> map (Mappings:: length ());
var_dump ( $ lengths );
// {0: 6, 1: 3, 2: 4, 3: 5, 4: 9}Или в Twig:
{{ dump ( words |it. map ( it . mappings . length )) }} Фильтрация преобразует одну коллекцию в другую, возможно более короткую. С помощью filter оценивается каждый элемент в коллекции, элементы, которые считаются empty будут отклонены, а элементы, которые не являются empty будут пропущены через фильтр.
Например, мы можем использовать замыкание, чтобы определить, является ли элемент дорогим, тогда filter будет пропускать только дорогие элементы:
use function Zicht itertools iterable ;
$ isExpensive = fn ( $ value , $ key ) => $ value [ ' price ' ] >= 10000 ;
$ expensiveTypes = iterable ( $ vehicles )-> filter ( $ isExpensive )-> map ( ' type ' );
var_dump ( $ expensiveTypes );
// {1: 'car', 9: 'car'}Или в Twig:
{{ dump ( vehicles |it. filter ( vehicle => vehicle . price >= 10000 ).map( ' type ' )) }} Используя стратегию получения строк, мы можем получить только те $vehicles , которые считаются крутыми. Например:
use function Zicht itertools iterable ;
$ coolVehicleTypes = iterable ( $ vehicles )-> filter ( ' is_cool ' )-> map ( ' type ' );
var_dump ( $ coolVehicleTypes );
// {5: 'unicicle', 9: 'car'}Или в Twig:
{{ dump ( vehicles |it. filter ( ' is_cool ' ).map( ' type ' )) }} В filter.php доступно несколько распространенных замыканий фильтров. Вызов этой функции возвращает замыкание, которое можно передать в filter . Например:
use Zicht itertools util Filters ;
use function Zicht itertools iterable ;
$ movieWords = iterable ( $ words )-> filter (Filters:: in ([ ' Shining ' , ' My little pony ' , ' Goonies ' ]));
var_dump ( $ movieWords );
// {1: 'Goonies'}Или в Twig:
{{ dump ( words |it. filter ( it . filters . in ([ ' Shining ' , " My little pony', 'Goonies'])) }} sorted преобразует одну коллекцию в другую коллекцию равного размера, но с возможным переупорядочением элементов.
Например, используя стратегию получения null значений, которая используется по умолчанию, мы будем сортировать значения элементов в порядке возрастания:
use function Zicht itertools iterable ;
$ ordered = iterable ( $ numbers )-> sorted ();
var_dump ( $ ordered );
// {0: 1, 2: 2, 1: 3, 4: 4, 3: 5}Или в Twig:
{{ dump ( numbers |it. sorted }}Алгоритм сортировки сохранит ключи и гарантированно будет стабильным. Т.е. когда элементы сортируются по одному и тому же значению, порядок сортировки гарантированно совпадает с порядком входных элементов. Это противоречит стандартным функциям сортировки PHP.
Используя стратегию получения замыкания, возвращаемое значение используется для определения порядка. Замыкание вызывается ровно один раз для каждого элемента, и полученные значения должны быть сопоставимы. Например:
use function Zicht itertools iterable ;
$ getLower = fn ( $ value , $ key ) => strtolower ( $ value );
$ ordered = iterable ( $ words )-> sorted ( $ getLower );
var_dump ( $ ordered );
// {3: 'Bland', 1: 'Goonies', 2: 'oven', 0: 'Useful', 4: 'notorious'};Mappings.php предоставляет замыкание сопоставления, которое возвращает случайное число. Это можно использовать для сортировки коллекции в случайном порядке. Например:
use Zicht itertools util Mappings ;
use function Zicht itertools iterable ;
$ randomized = iterable ( $ words )-> sorted (Mappings:: random ());
var_dump ( $ randomized );
// {... randomly ordere words ...}Или в Twig:
{{ dump ( words |it. sorted ( it . mappings . random )) }} groupBy преобразует одну коллекцию в одну или несколько коллекций, которые группируют элементы по определенному критерию.
Например, используя стратегию получения строк, мы можем сгруппировать все $vehicles одного типа вместе:
use function Zicht itertools iterable ;
$ vehiclesByType = iterable ( $ vehicles )-> groupBy ( ' type ' );
var_dump ( $ vehiclesByType );
// {'bike': {1: [...]}, 'car': {0: [...], 3: [...]} 'unicicle': {2: [...]}}Или в Twig:
{{ dump ( vehicles |it. groupBy ( ' type ' )) }} Это не значит, что исходные ключи от транспортных средств по-прежнему являются частью результирующих групп, а элементы внутри каждой группы сохраняют порядок, который они имели во входных данных, то есть используется стабильная сортировка, предоставляемая sorted .
reduce преобразует коллекцию в одно значение, вызывая замыкание двух аргументов кумулятивно для элементов коллекции, слева направо.
Например, без каких-либо аргументов reduce добавит все элементы коллекции вместе:
use function Zicht itertools iterable ;
$ sum = iterable ( $ numbers )-> reduce ();
var_dump ( $ sum );
// 15Или в Twig:
{{ dump ( numbers |it. reduce ) }}В приведенном выше примере используемое замыкание по умолчанию выглядит следующим образом:
public static function add ( $ a , $ b ): Closure
{
return $ a + $ b ;
} Учитывая, что $numbers состоит из элементов {1, 3, 2, 5, 4}, замыкание add вызывается четыре раза:
$ sum = Reductions:: add (Reductions:: add (Reductions:: add (Reductions:: add (( 1 , 3 ), 2 ), 5 ), 4 ));
var_dump ( $ sum );
// 15 В Reduction.php доступно несколько распространенных замыканий сокращения. Вызов этих функций возвращает замыкание, которое можно передать в reduction . Например:
use Zicht itertools util Reductions ;
use function Zicht itertools iterable ;
$ scentence = iterable ( $ words )-> reduce (Reductions:: join ( ' - ' ));
var_dump ( $ scentence );
// 'Useful - Goonies - oven - Bland - notorious'Или в Twig:
{{ dump ( words |it. reduce ( it . reductions . join ( ' - ' )) }} Еще одно распространенное сокращение — объединение нескольких списков в один список. Мы называем этот процесс коллапсом. Этот процесс также может быть достигнут с помощью reduce и объединения в chain , однако, поскольку он используется часто, помощник collapse упрощает его использование, например:
use function Zicht itertools iterable ;
$ flat = iterable ([[ ' one ' , ' two ' ], [ ' three ' ]])-> collapse ();
var_dump ( $ flat );
// {0: 'one', 1: 'two', 0: 'three'}Или в Twig:
{% set data = [[ ' one ' , ' two ' ], [ ' three ' ]] %}
{{ dump ( data |it. collapse ) }}