Alat Iterator, atau disingkat itertools , adalah kumpulan alat praktis untuk menangani urutan data seperti array, iterator, dan string. Beberapa penamaan dan API didasarkan pada itertools Python.
Contoh
Operasi umum meliputi:
map
dan mapBy
filter
, difference
sorted
groupBy
accumulate
, collapse
, dan reduce
Untuk menggunakan filter/fungsi itertools yang tersedia melalui Twig, cukup tambahkan definisi layanan ini di config/services.yaml
Anda
Zicht itertools twigExtension :
tags : ['twig.extension']
composer test
composer lint
Contoh di bawah ini akan menggunakan data berikut untuk mengilustrasikan cara kerja berbagai alat 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 ,
],
];
Dengan contoh data di atas, inilah cara Anda menggunakan itertools untuk mendapatkan semua warna unik mobil dalam urutan abjad:
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'}
Anda dapat mencapai hal yang sama di 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 %}
Banyak itertools yang dapat melewati parameter $strategy
. Parameter ini digunakan untuk mendapatkan nilai dari elemen-elemen dalam koleksi. $strategy
dapat berupa salah satu dari tiga hal berikut:
null, dalam hal ini elemen itu sendiri dikembalikan. Misalnya:
use function Zicht itertools iterable ;
$ result = iterable ( $ words )-> map ( null );
var_dump ( $ result );
// {0: 'Useful', 1: 'Goonies', 2: 'oven', 3: 'Bland', 4: 'notorious'}
Atau di Ranting:
{{ dump ( word |it. map ) }}
penutupan, dalam hal ini penutupan dipanggil dengan nilai elemen dan kunci sebagai parameter yang akan digunakan untuk menghitung nilai kembalian. Misalnya:
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}
Atau di Ranting:
{{ dump ( numbers |it. map ( num => 2 * num )) }}
sebuah string, dalam hal ini string ini digunakan untuk membuat penutupan yang mencoba menemukan properti publik, metode, atau indeks array. Misalnya:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> map ( ' type ' );
var_dump ( $ result );
// {0: 'car', 1: 'bike', 2: 'unicicle', 3: 'car'}
Atau di Ranting:
{{ dump ( word |it. map ) }}
String dapat terdiri dari beberapa kata yang dipisahkan titik, memungkinkan akses ke properti bertingkat, metode, dan indeks array.
Jika salah satu kata dalam string tidak dapat diselesaikan menjadi properti, metode, atau indeks array yang ada, nilai null
akan dikembalikan. Misalnya:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> map ( ' colors.2 ' );
var_dump ( $ result );
// {0: 'blue', 1: 'blue', 2: null, 3: null}
Atau di Ranting:
{{ dump ( vehicles |it. map ( ' colors.2 ' )) }}
Salah satu cara menggunakan Alat Iterator adalah dengan mengubah array, Iterator, string, dll menjadi IterableIterator
. Kelas ini menyediakan antarmuka yang lancar untuk semua operasi umum. Misalnya:
use function Zicht itertools iterable ;
$ result = iterable ( $ vehicles )-> filter ( ' is_cool ' )-> mapBy ( ' id ' )-> map ( ' type ' );
var_dump ( $ result );
// {5: 'unicicle', 9: 'car'}
Atau di Ranting:
{{ dump ( vehicles |it. filter ( ' is_cool ' ).mapBy( ' id ' ).map( ' type ' )) }}
Pemetaan mengubah satu koleksi menjadi koleksi lain yang panjangnya sama. Menggunakan map
memungkinkan manipulasi elemen sementara mapBy
memungkinkan manipulasi kunci koleksi.
Misalnya, kita dapat menggunakan penutupan untuk membuat judul untuk setiap elemen di $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'}
Dengan menggunakan strategi pengambil string, kita dapat dengan mudah mendapatkan tipe untuk setiap elemen di $vehicles
yang dipetakan oleh pengidentifikasi kendaraan. Misalnya:
use function Zicht itertools iterable ;
$ types = iterable ( $ vehicles )-> mapBy ( ' id ' )-> map ( ' type ' );
var_dump ( $ types );
// {1: 'car', 2: 'bike', 5: 'unicicle', 9: 'car'}
Atau di Ranting:
{{ dump ( vehicles |it. mapBy ( ' id ' ).map( ' type ' )) }}
Ada beberapa penutupan pemetaan umum yang tersedia di maps.php. Memanggil fungsi-fungsi ini akan mengembalikan penutupan yang dapat diteruskan ke map
dan mapBy
. Misalnya:
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}
Atau di Ranting:
{{ dump ( words |it. map ( it . mappings . length )) }}
Pemfilteran mengubah satu koleksi menjadi koleksi lain, mungkin lebih pendek. Dengan menggunakan filter
setiap elemen dalam koleksi dievaluasi, elemen yang dianggap empty
akan ditolak, sedangkan elemen yang tidak empty
akan diizinkan melewati filter.
Misalnya, kita dapat menggunakan penutupan untuk menentukan apakah suatu elemen mahal, filter
hanya akan mengizinkan elemen mahal tersebut melewati:
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'}
Atau di Ranting:
{{ dump ( vehicles |it. filter ( vehicle => vehicle . price >= 10000 ).map( ' type ' )) }}
Dengan menggunakan strategi string getter kita hanya bisa mendapatkan $vehicles
yang dianggap keren. Misalnya:
use function Zicht itertools iterable ;
$ coolVehicleTypes = iterable ( $ vehicles )-> filter ( ' is_cool ' )-> map ( ' type ' );
var_dump ( $ coolVehicleTypes );
// {5: 'unicicle', 9: 'car'}
Atau di Ranting:
{{ dump ( vehicles |it. filter ( ' is_cool ' ).map( ' type ' )) }}
Ada beberapa penutupan filter umum yang tersedia di filter.php. Memanggil fungsi ini akan mengembalikan penutupan yang dapat diteruskan ke filter
. Misalnya:
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'}
Atau di Ranting:
{{ dump ( words |it. filter ( it . filters . in ([ ' Shining ' , " My little pony', 'Goonies'])) }}
sorted
mengubah satu koleksi menjadi koleksi lain dengan ukuran yang sama tetapi dengan elemen yang mungkin disusun ulang.
Misalnya, dengan menggunakan strategi pengambil null
, yang merupakan default, kita akan mengurutkan menggunakan nilai elemen dalam urutan menaik:
use function Zicht itertools iterable ;
$ ordered = iterable ( $ numbers )-> sorted ();
var_dump ( $ ordered );
// {0: 1, 2: 2, 1: 3, 4: 4, 3: 5}
Atau di Ranting:
{{ dump ( numbers |it. sorted }}
Algoritme pengurutan akan mempertahankan kunci dan dijamin stabil. Yaitu ketika elemen diurutkan menggunakan nilai yang sama, maka urutan pengurutannya dijamin sama dengan urutan elemen masukan. Ini bertentangan dengan fungsi pengurutan standar PHP.
Dengan menggunakan strategi pengambil penutupan, nilai yang dikembalikan digunakan untuk menentukan pesanan. Penutupan ini dipanggil tepat satu kali per elemen, dan nilai yang dihasilkan harus sebanding. Misalnya:
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'};
maps.php menyediakan penutupan pemetaan yang mengembalikan nomor acak. Ini dapat digunakan untuk mengurutkan koleksi dalam urutan acak. Misalnya:
use Zicht itertools util Mappings ;
use function Zicht itertools iterable ;
$ randomized = iterable ( $ words )-> sorted (Mappings:: random ());
var_dump ( $ randomized );
// {... randomly ordere words ...}
Atau di Ranting:
{{ dump ( words |it. sorted ( it . mappings . random )) }}
groupBy
mengonversi satu koleksi menjadi satu atau lebih koleksi yang mengelompokkan elemen berdasarkan kriteria tertentu.
Misalnya, dengan menggunakan strategi pengambil string, kita dapat mengelompokkan semua $vehicles
yang bertipe sama menjadi satu:
use function Zicht itertools iterable ;
$ vehiclesByType = iterable ( $ vehicles )-> groupBy ( ' type ' );
var_dump ( $ vehiclesByType );
// {'bike': {1: [...]}, 'car': {0: [...], 3: [...]} 'unicicle': {2: [...]}}
Atau di Ranting:
{{ dump ( vehicles |it. groupBy ( ' type ' )) }}
Bukan berarti kunci asli dari kendaraan masih menjadi bagian dari grup yang dihasilkan, dan elemen dalam setiap grup menjaga urutan inputnya, yaitu menggunakan penyortiran stabil yang disediakan oleh sorted
.
reduce
mengubah koleksi menjadi nilai tunggal dengan memanggil penutupan dua argumen secara kumulatif ke elemen dalam koleksi, dari kiri ke kanan.
Misalnya, tanpa argumen apa pun, reduce
akan menjumlahkan semua elemen koleksi:
use function Zicht itertools iterable ;
$ sum = iterable ( $ numbers )-> reduce ();
var_dump ( $ sum );
// 15
Atau di Ranting:
{{ dump ( numbers |it. reduce ) }}
Pada contoh di atas, penutupan default yang digunakan terlihat seperti ini:
public static function add ( $ a , $ b ): Closure
{
return $ a + $ b ;
}
Mengingat $numbers
terdiri dari elemen {1, 3, 2, 5, 4}, penutupan add
dipanggil empat kali:
$ sum = Reductions:: add (Reductions:: add (Reductions:: add (Reductions:: add (( 1 , 3 ), 2 ), 5 ), 4 ));
var_dump ( $ sum );
// 15
Ada beberapa penutupan reduksi umum yang tersedia di reduksi.php. Memanggil fungsi-fungsi ini akan mengembalikan penutupan yang dapat diteruskan ke reduction
. Misalnya:
use Zicht itertools util Reductions ;
use function Zicht itertools iterable ;
$ scentence = iterable ( $ words )-> reduce (Reductions:: join ( ' - ' ));
var_dump ( $ scentence );
// 'Useful - Goonies - oven - Bland - notorious'
Atau di Ranting:
{{ dump ( words |it. reduce ( it . reductions . join ( ' - ' )) }}
Pengurangan umum lainnya adalah merangkai beberapa daftar menjadi satu daftar. Kami menyebut proses ini gagal. Proses ini juga dapat dicapai dengan menggunakan reduce
dan chain
bersama-sama, namun karena sering digunakan, pembantu collapse
membuat penggunaannya lebih mudah, misalnya:
use function Zicht itertools iterable ;
$ flat = iterable ([[ ' one ' , ' two ' ], [ ' three ' ]])-> collapse ();
var_dump ( $ flat );
// {0: 'one', 1: 'two', 0: 'three'}
Atau di Ranting:
{% set data = [[ ' one ' , ' two ' ], [ ' three ' ]] %}
{{ dump ( data |it. collapse ) }}