أدوات التكرار، أو itertools باختصار، عبارة عن مجموعة من الأدوات الملائمة للتعامل مع تسلسلات البيانات مثل المصفوفات والمكررات والسلاسل. تعتمد بعض عمليات التسمية وواجهة برمجة التطبيقات (API) على أدوات Python itertools .
أمثلة
تشمل العمليات الشائعة ما يلي:
map
و mapBy
filter
، difference
sorted
groupBy
accumulate
، collapse
، reduce
من أجل استخدام مرشحات/وظائف itertools المتاحة عبر Twig، ما عليك سوى إضافة تعريف الخدمة هذا في config/services.yaml
الخاص بك
Zicht itertools twigExtension :
tags : ['twig.extension']
composer test
composer 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'}
أو في غصين:
{{ 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}
أو في غصين:
{{ 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'}
أو في غصين:
{{ 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}
أو في غصين:
{{ 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'}
أو في غصين:
{{ 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'}
باستخدام استراتيجية getter يمكننا بسهولة الحصول على أنواع كل عنصر في $vehicles
المعينة بواسطة معرفات المركبات. على سبيل المثال:
use function Zicht itertools iterable ;
$ types = iterable ( $ vehicles )-> mapBy ( ' id ' )-> map ( ' type ' );
var_dump ( $ types );
// {1: 'car', 2: 'bike', 5: 'unicicle', 9: 'car'}
أو في غصين:
{{ 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}
أو في غصين:
{{ 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'}
أو في غصين:
{{ dump ( vehicles |it. filter ( vehicle => vehicle . price >= 10000 ).map( ' type ' )) }}
باستخدام استراتيجية getter يمكننا الحصول فقط على $vehicles
التي تعتبر رائعة. على سبيل المثال:
use function Zicht itertools iterable ;
$ coolVehicleTypes = iterable ( $ vehicles )-> filter ( ' is_cool ' )-> map ( ' type ' );
var_dump ( $ coolVehicleTypes );
// {5: 'unicicle', 9: 'car'}
أو في غصين:
{{ 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'}
أو في غصين:
{{ dump ( words |it. filter ( it . filters . in ([ ' Shining ' , " My little pony', 'Goonies'])) }}
يقوم sorted
بتحويل مجموعة واحدة إلى مجموعة أخرى بنفس الحجم ولكن مع إمكانية إعادة ترتيب العناصر.
على سبيل المثال، باستخدام إستراتيجية null
getter، وهي الإستراتيجية الافتراضية، سنقوم بالفرز باستخدام قيم العناصر بترتيب تصاعدي:
use function Zicht itertools iterable ;
$ ordered = iterable ( $ numbers )-> sorted ();
var_dump ( $ ordered );
// {0: 1, 2: 2, 1: 3, 4: 4, 3: 5}
أو في غصين:
{{ dump ( numbers |it. sorted }}
ستحافظ خوارزمية الفرز على المفاتيح وتضمن ثباتها. أي أنه عندما يتم فرز العناصر باستخدام نفس القيمة، فإنه يتم ضمان أن يكون ترتيب الفرز هو نفس ترتيب عناصر الإدخال. وهذا يتعارض مع وظائف الفرز القياسية PHP.
باستخدام استراتيجية getter الإغلاق يتم استخدام القيمة التي تم إرجاعها لتحديد الطلب. يتم استدعاء الإغلاق مرة واحدة بالضبط لكل عنصر، ويجب أن تكون القيم الناتجة قابلة للمقارنة. على سبيل المثال:
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 ...}
أو في غصين:
{{ dump ( words |it. sorted ( it . mappings . random )) }}
يقوم groupBy
بتحويل مجموعة واحدة إلى مجموعة واحدة أو أكثر تجمع العناصر معًا وفقًا لمعايير محددة.
على سبيل المثال، باستخدام استراتيجية getter يمكننا تجميع جميع $vehicles
من نفس النوع معًا:
use function Zicht itertools iterable ;
$ vehiclesByType = iterable ( $ vehicles )-> groupBy ( ' type ' );
var_dump ( $ vehiclesByType );
// {'bike': {1: [...]}, 'car': {0: [...], 3: [...]} 'unicicle': {2: [...]}}
أو في غصين:
{{ dump ( vehicles |it. groupBy ( ' type ' )) }}
لا يعني ذلك أن المفاتيح الأصلية للمركبات لا تزال جزءًا من المجموعات الناتجة، وأن العناصر الموجودة داخل كل مجموعة تحافظ على الترتيب الذي كانت عليه في الإدخال، أي أنها تستخدم الفرز المستقر المقدم بواسطة sorted
.
reduce
تحويل مجموعة إلى قيمة واحدة عن طريق استدعاء إغلاق وسيطتين بشكل تراكمي للعناصر الموجودة في المجموعة، من اليسار إلى اليمين.
على سبيل المثال، بدون أي وسيطات، سيضيف reduce
كل عناصر المجموعة معًا:
use function Zicht itertools iterable ;
$ sum = iterable ( $ numbers )-> reduce ();
var_dump ( $ sum );
// 15
أو في غصين:
{{ 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
هناك العديد من عمليات إغلاق التخفيض الشائعة المتاحة في موقع تخفيضات.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'
أو في غصين:
{{ 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'}
أو في غصين:
{% set data = [[ ' one ' , ' two ' ], [ ' three ' ]] %}
{{ dump ( data |it. collapse ) }}