PHP array delete by value (not key): نظرة تحت الغطاء
\n\nتخيل أنك تكتب سكربت PHP وتعالج قائمة منتجات، وفجأة تحتاج إلى حذف عنصر بسعر أو اسم معين من المصفوفة. أنت تعرف القيمة تمامًا — مثل "تفاح" — لكنك لا تعرف في أي مفتاح توجد. موقف مألوف؟ إذا كان الأمر كذلك، فأنت لست وحدك: سؤال "PHP array delete by value (not key)" يجمع آلاف المشاهدات على Stack Overflow. وهذا ليس من قبيل الصدفة.
في PHP لا توجد دالة مدمجة array_remove_by_value(). لذلك يلجأ المطورون إلى الحيل: البعض يكتب حلقة تكرارية، والبعض يستخدم array_search مع unset، والبعض الآخر يستخدم array_diff أو array_filter. لكن ماذا يحدث داخل هذه الدوال؟ أي طريقة أسرع؟ ولماذا قد يعمل نفس الكود بشكل مختلف في إصدارات PHP المختلفة؟
في هذه المقالة، لن نقدم لك حلًا جاهزًا فقط — بل سنلقي نظرة تحت الغطاء لكل طريقة، ونحلل أداءها والمزالق المحتملة. وسنعرض أيضًا حالة عملية من حياة مطور باك إند. هيا بنا!
\n\nالطريقة التقليدية: array_search + unset
\n\nالإجابة الأكثر شيوعًا على Stack Overflow تبدو كالتالي:
\n\n<?php\n$array = ['تفاح', 'كمثرى', 'برتقال', 'كمثرى'];\n$value = 'كمثرى';\n\nif (($key = array_search($value, $array)) !== false) {\n unset($array[$key]);\n}\n?>\n\nهذا الكود يجد أول ظهور للقيمة ويحذفه. لكن دعنا نفهم ما يحدث بالضبط.
\n\nكيف تعمل array_search
\n\narray_search() هي عملية بحث خطي. تمر PHP عبر المصفوفة من البداية إلى النهاية، وتقارن كل قيمة بالقيمة المطلوبة. المقارنة الافتراضية هي غير صارمة (==)، أي أن 1 و '1' يعتبران متساويين. إذا كنت بحاجة إلى مقارنة صارمة (===)، قم بتمرير المعامل الثالث true:
<?php\n$array = [0, '0', 1];\n$key = array_search('0', $array, true); // سيعيد 1 (السلسلة '0')، وليس 0\n?>\n\nإذا لم يتم العثور على القيمة، ترجع الدالة false. لذلك التحقق !== false إلزامي — وإلا فإن unset($array[0]) سيحذف العنصر الأول إذا كانت القيمة موجودة في المفتاح 0.
المأزق: unset لا يعيد ترتيب المفاتيح
\n\nبعد unset، تبقى المصفوفة ترابطية — المفاتيح الرقمية لا تتغير. إذا كنت بحاجة إلى مصفوفة كثيفة بمفاتيح متسلسلة، استخدم array_values():
<?php\n$array = ['تفاح', 'كمثرى', 'برتقال'];\nunset($array[1]);\n$array = array_values($array); // ['تفاح', 'برتقال'] بمفاتيح 0 و 1\n?>\n\nلكن تذكر: array_values() تنشئ مصفوفة جديدة، مما يزيد من استهلاك الذاكرة.
حذف جميع التكرارات: array_diff
\n\nإذا كنت بحاجة إلى حذف جميع العناصر ذات القيمة المحددة، فإن استخدام array_search في حلقة تكرارية ليس فكرة جيدة. الطريقة الأكثر أناقة هي استخدام array_diff():
<?php\n$array = ['تفاح', 'كمثرى', 'برتقال', 'كمثرى'];\n$array = array_diff($array, ['كمثرى']);\n// النتيجة: ['تفاح', 'برتقال'] (المفاتيح محفوظة)\n?>\n\nترجع الدالة مصفوفة جديدة تم حذف جميع العناصر المطابقة للقيم في المصفوفة الثانية منها. داخليًا، تستخدم PHP جدول تجزئة للمصفوفة الثانية، لذلك تتم العملية بتعقيد زمني O(n + m)، حيث n هو حجم المصفوفة الأولى و m هو حجم الثانية.
\n\nمهم: array_diff تقارن القيم كسلاسل نصية ((string) $elem1 === (string) $elem2). بالنسبة للأنواع المختلطة، قد يعطي هذا نتيجة غير متوقعة:
<?php\n$array = [0, '0', false];\n$result = array_diff($array, [0]);\n// النتيجة: