Die Iterator-Tools, kurz itertools , sind eine Sammlung praktischer Tools zur Verarbeitung von Datensequenzen wie Arrays, Iteratoren und Strings. Ein Teil der Benennung und API basiert auf den Python- itertools .
Beispiele
Zu den üblichen Operationen gehören:
map
und mapBy
filter
, difference
sorted
groupBy
accumulate
, collapse
und reduce
Um die verfügbaren itertools -Filter/-Funktionen über Twig zu nutzen, fügen Sie einfach diese Service-Definition in Ihre config/services.yaml
ein
Zicht itertools twigExtension :
tags : ['twig.extension']
composer test
composer lint
In den folgenden Beispielen werden die folgenden Daten verwendet, um die Funktionsweise verschiedener Iterator-Tools zu veranschaulichen:
$ 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 ,
],
];
Mit den obigen Beispieldaten können Sie itertools folgendermaßen verwenden, um alle einzigartigen Farben der Autos in alphabetischer Reihenfolge abzurufen:
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'}
Dasselbe können Sie in Twig erreichen:
{% for vehicle_color in vehicles
|it. filter ( it . filters . equals ( ' car ' , ' type ' ))
|it. map ( ' colors ' )
|it. collapse
|it. unique
|it. sorted
%}
{{ vehicle_color }}
{% endfor %}
Vielen itertools kann ein $strategy
Parameter übergeben werden. Dieser Parameter wird verwendet, um einen Wert aus den Elementen in der Sammlung zu erhalten. Die $strategy
kann eines von drei Dingen sein:
null, in diesem Fall wird das Element selbst zurückgegeben. Zum Beispiel:
use function Zicht itertools iterable ;
$ result = iterable ( $ words )-> map ( null );
var_dump ( $ result );
// {0: 'Useful', 1: 'Goonies', 2: 'oven', 3: 'Bland', 4: 'notorious'}
Oder in Zweig:
{{ dump ( word |it. map ) }}
ein Abschluss. In diesem Fall wird der Abschluss mit dem Elementwert und dem Schlüssel als Parameter aufgerufen, die zur Berechnung eines Rückgabewerts verwendet werden. Zum Beispiel:
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}
Oder in Zweig:
{{ dump ( numbers |it. map ( num => 2 * num )) }}
eine Zeichenfolge. In diesem Fall wird diese Zeichenfolge verwendet, um einen Abschluss zu erstellen, der versucht, öffentliche Eigenschaften, Methoden oder Array-Indizes zu finden. Zum Beispiel:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> map ( ' type ' );
var_dump ( $ result );
// {0: 'car', 1: 'bike', 2: 'unicicle', 3: 'car'}
Oder in Zweig:
{{ dump ( word |it. map ) }}
Die Zeichenfolge kann aus mehreren durch Punkte getrennten Wörtern bestehen und ermöglicht den Zugriff auf verschachtelte Eigenschaften, Methoden und Array-Indizes.
Wenn eines der Wörter in der Zeichenfolge nicht in eine vorhandene Eigenschaft, Methode oder einen Array-Index aufgelöst werden kann, wird der Wert null
zurückgegeben. Zum Beispiel:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> map ( ' colors.2 ' );
var_dump ( $ result );
// {0: 'blue', 1: 'blue', 2: null, 3: null}
Oder in Zweig:
{{ dump ( vehicles |it. map ( ' colors.2 ' )) }}
Eine Möglichkeit, die Iterator-Tools zu verwenden, besteht darin, das Array, den Iterator, die Zeichenfolge usw. in einen IterableIterator
zu konvertieren. Diese Klasse bietet eine fließende Schnittstelle zu allen gängigen Vorgängen. Zum Beispiel:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> filter ( ' is_cool ' )-> mapBy ( ' id ' )-> map ( ' type ' );
var_dump ( $ result );
// {5: 'unicicle', 9: 'car'}
Oder in Zweig:
{{ dump ( vehicles |it. filter ( ' is_cool ' ).mapBy( ' id ' ).map( ' type ' )) }}
Beim Mapping wird eine Sammlung in eine andere Sammlung gleicher Länge konvertiert. Die Verwendung von map
ermöglicht die Manipulation der Elemente, während mapBy
die Manipulation der Sammlungsschlüssel ermöglicht.
Beispielsweise können wir einen Abschluss verwenden, um für jedes Element in $vehicles
einen Titel zu erstellen:
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'}
Mit der String-Getter-Strategie können wir leicht die Typen für jedes Element in $vehicles
ermitteln, das durch die Fahrzeugkennungen zugeordnet wird. Zum Beispiel:
use function Zicht itertools iterable ;
$ types = iterable ( $ vehicles )-> mapBy ( ' id ' )-> map ( ' type ' );
var_dump ( $ types );
// {1: 'car', 2: 'bike', 5: 'unicicle', 9: 'car'}
Oder in Zweig:
{{ dump ( vehicles |it. mapBy ( ' id ' ).map( ' type ' )) }}
In „mappings.php“ sind mehrere gängige Mapping-Abschlüsse verfügbar. Der Aufruf dieser Funktionen gibt einen Abschluss zurück, der an map
und mapBy
übergeben werden kann. Zum Beispiel:
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}
Oder in Zweig:
{{ dump ( words |it. map ( it . mappings . length )) }}
Beim Filtern wird eine Sammlung in eine andere, möglicherweise kürzere Sammlung konvertiert. Mithilfe filter
wird jedes Element in der Sammlung ausgewertet. Die Elemente, die empty
gelten, werden abgelehnt, während die Elemente, die nicht empty
sind, den Filter passieren dürfen.
Beispielsweise können wir einen Verschluss verwenden, um festzustellen, ob ein Element teuer ist. Der filter
lässt dann nur die teuren Elemente durch:
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'}
Oder in Zweig:
{{ dump ( vehicles |it. filter ( vehicle => vehicle . price >= 10000 ).map( ' type ' )) }}
Mit der String-Getter-Strategie können wir nur die $vehicles
erhalten, die als cool gelten. Zum Beispiel:
use function Zicht itertools iterable ;
$ coolVehicleTypes = iterable ( $ vehicles )-> filter ( ' is_cool ' )-> map ( ' type ' );
var_dump ( $ coolVehicleTypes );
// {5: 'unicicle', 9: 'car'}
Oder in Zweig:
{{ dump ( vehicles |it. filter ( ' is_cool ' ).map( ' type ' )) }}
In filter.php sind mehrere gängige Filterverschlüsse verfügbar. Der Aufruf dieser Funktion gibt einen Abschluss zurück, der an filter
übergeben werden kann. Zum Beispiel:
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'}
Oder in Zweig:
{{ dump ( words |it. filter ( it . filters . in ([ ' Shining ' , " My little pony', 'Goonies'])) }}
sorted
konvertiert eine Sammlung in eine andere Sammlung gleicher Größe, wobei die Elemente jedoch möglicherweise neu angeordnet werden.
Mit der standardmäßigen null
Getter-Strategie sortieren wir beispielsweise nach den Elementwerten in aufsteigender Reihenfolge:
use function Zicht itertools iterable ;
$ ordered = iterable ( $ numbers )-> sorted ();
var_dump ( $ ordered );
// {0: 1, 2: 2, 1: 3, 4: 4, 3: 5}
Oder in Zweig:
{{ dump ( numbers |it. sorted }}
Der Sortieralgorithmus behält die Schlüssel bei und ist garantiert stabil. Wenn also Elemente nach demselben Wert sortiert werden, stimmt die Sortierreihenfolge garantiert mit der Reihenfolge der Eingabeelemente überein. Dies steht im Widerspruch zu den standardmäßigen PHP-Sortierfunktionen.
Bei der Closed-Getter-Strategie wird der zurückgegebene Wert zur Bestimmung der Reihenfolge verwendet. Der Abschluss wird genau einmal pro Element aufgerufen und die resultierenden Werte müssen vergleichbar sein. Zum Beispiel:
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'};
Die „mappings.php“ stellt einen Mapping-Abschluss bereit, der eine Zufallszahl zurückgibt. Dies kann verwendet werden, um eine Sammlung in zufälliger Reihenfolge zu sortieren. Zum Beispiel:
use Zicht itertools util Mappings ;
use function Zicht itertools iterable ;
$ randomized = iterable ( $ words )-> sorted (Mappings:: random ());
var_dump ( $ randomized );
// {... randomly ordere words ...}
Oder in Zweig:
{{ dump ( words |it. sorted ( it . mappings . random )) }}
groupBy
wandelt eine Sammlung in eine oder mehrere Sammlungen um, die die Elemente nach einem bestimmten Kriterium gruppieren.
Mit der String-Getter-Strategie können wir beispielsweise alle $vehicles
desselben Typs gruppieren:
use function Zicht itertools iterable ;
$ vehiclesByType = iterable ( $ vehicles )-> groupBy ( ' type ' );
var_dump ( $ vehiclesByType );
// {'bike': {1: [...]}, 'car': {0: [...], 3: [...]} 'unicicle': {2: [...]}}
Oder in Zweig:
{{ dump ( vehicles |it. groupBy ( ' type ' )) }}
Nicht, dass die Originalschlüssel der Fahrzeuge immer noch Teil der resultierenden Gruppen sind, und die Elemente innerhalb jeder Gruppe behalten die Reihenfolge bei, die sie in der Eingabe hatten, d. h. es wird die stabile Sortierung verwendet, die von sorted
bereitgestellt wird.
reduce
konvertiert eine Sammlung in einen einzelnen Wert, indem ein Abschluss zweier Argumente kumulativ für die Elemente in der Sammlung von links nach rechts aufgerufen wird.
Ohne Argumente addiert reduce
beispielsweise alle Elemente der Sammlung:
use function Zicht itertools iterable ;
$ sum = iterable ( $ numbers )-> reduce ();
var_dump ( $ sum );
// 15
Oder in Zweig:
{{ dump ( numbers |it. reduce ) }}
Im obigen Beispiel sieht der verwendete Standardverschluss folgendermaßen aus:
public static function add ( $ a , $ b ): Closure
{
return $ a + $ b ;
}
Da $numbers
aus den Elementen {1, 3, 2, 5, 4} besteht, wird der add
Abschluss viermal aufgerufen:
$ sum = Reductions:: add (Reductions:: add (Reductions:: add (Reductions:: add (( 1 , 3 ), 2 ), 5 ), 4 ));
var_dump ( $ sum );
// 15
In reductions.php sind mehrere gängige Reduktionsverschlüsse verfügbar. Der Aufruf dieser Funktionen gibt einen Abschluss zurück, der an reduction
übergeben werden kann. Zum Beispiel:
use Zicht itertools util Reductions ;
use function Zicht itertools iterable ;
$ scentence = iterable ( $ words )-> reduce (Reductions:: join ( ' - ' ));
var_dump ( $ scentence );
// 'Useful - Goonies - oven - Bland - notorious'
Oder in Zweig:
{{ dump ( words |it. reduce ( it . reductions . join ( ' - ' )) }}
Eine weitere häufige Reduzierung ist die Verkettung mehrerer Listen zu einer Liste. Wir nennen diesen Prozess Kollaps. Dieser Prozess kann auch durch die Kombination von reduce
und chain
“ erreicht werden. Da er jedoch häufig verwendet wird, erleichtert der collapse
Helfer die Verwendung, zum Beispiel:
use function Zicht itertools iterable ;
$ flat = iterable ([[ ' one ' , ' two ' ], [ ' three ' ]])-> collapse ();
var_dump ( $ flat );
// {0: 'one', 1: 'two', 0: 'three'}
Oder in Zweig:
{% set data = [[ ' one ' , ' two ' ], [ ' three ' ]] %}
{{ dump ( data |it. collapse ) }}