وهو أسرع:in_array() أو مجموعة من التعبيرات في PHP؟

StackOverflow https://stackoverflow.com/questions/324665

  •  11-07-2019
  •  | 
  •  

سؤال

هل من الأسرع القيام بما يلي:

 if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') { ... }

أو:

 if (!in_array($var, array('test1', 'test2', 'test3', 'test4') { ... }

هل هناك عدد من القيم وعند هذه النقطة يكون من الأسرع القيام بواحدة أو أخرى؟

(في هذه الحالة، المصفوفة المستخدمة في الخيار الثاني غير موجودة بالفعل.)

هل كانت مفيدة؟

المحلول

فما استقاموا لكم فاستقيموا بقوة أقترح فقط باستخدام in_array()، فإن أي اختلاف سرعة ستكون ضئيلة، ولكن القراءة من اختبار كل متغير على حدة أمر مروع.

ولمجرد التسلية وهنا اختبار ركضت:

$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
$end = microtime(true);

print "Time1: ". ($end - $start)."<br />";

$start2 = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!in_array($var, $array) ) {}
}
$end2 = microtime(true);

print "Time2: ".($end2 - $start2)."<br />";

// Time1: 1.12536692619
// Time2: 1.57462596893

ملحوظة تافهة قليلا لمشاهدة ل، إذا لم يتم تعيين $var، طريقة 1 وقتا أطول بكثير (اعتمادا على عدد الشروط التي اختبار)

نصائح أخرى

لاحظ أنه إذا كنت تبحث لتحل محل مجموعة من البيانات !==، يجب تمرير المعلمة الثالثة إلى <لأ href = "http://uk.php.net/manual/en/function.in-array. فب "يختلط =" noreferrer "> in_array كما true، التي تفرض اكتب التدقيق على العناصر الموجودة في مجموعة.

و!= العادية لا يتطلب هذا، ومن الواضح.

والأول سيكون أسرع - ثاني لديها الكثير من النفقات العامة: إنشاء مجموعة، استدعاء دالة، والبحث في مجموعة ...

ولكن، وكما قلت في سؤال بضع إجابات أسفل، والتحسين من السابق لأوانه هو أصل كل الشرور. يجب عليك كتابة التعليمات البرمجية لتكون قابلة للقراءة، ثم <م> إذا فإنه يحتاج إلى أن يكون الأمثل الشخصية، ثم الأمثل.

وتحرير:

وبلدي توقيت مع @ كود أوين (PHP 5.2.6 / ويندوز):

Time1: 1.33601498604
Time2: 4.9349629879

وتحريك مجموعة (...) داخل الحلقة، كما هو الحال في هذا السؤال:

Time1: 1.34736609459
Time2: 6.29464697838

وin_array سوف يكون أسرع لأعداد كبيرة من العناصر. "كبيرة" يجري ذاتية جدا استنادا إلى الكثير من العوامل المتعلقة البيانات وجهاز الكمبيوتر الخاص بك. منذ كنت طالبا، أفترض أنك لا تتعامل مع عدد تافهة من العناصر. لقوائم أطول، حذرهم هذه المعلومات ، وقياس الأداء مع مجموعة وانقلبت بحيث فب يمكن الاستفادة عمليات البحث التجزئة بدلا من البحث الخطي. لمجموعة "ثابت" أن قرص قد لا تحسين الأداء، ولكنه أيضا قد.

<ع> استخدام رمز اختبار أوين، مع مجموعة وانقلبت والمزيد من التكرار للحصول على نتائج أكثر اتساقا:

$array2 = array_flip($array);
$iterations = 10000000;

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array2[$var])) {}
}
$end = microtime(true);
print "Time3: ".($end - $start)."<br />";

Time1: 12.875
Time2: 13.7037701607
Time3: 3.70514011383

مرحبًا، لقد أخذت هذه الحالة إلى أقصى الحدود وأشرت إلى أنه مع زيادة عدد القيم، تكون المقارنة البسيطة لا الطريقة الأكثر أداء.

هنا هو الكود الخاص بي:

$var = 'test';
$num_values = 1000;
$iterations = 1000000;
print "\nComparison performance test with ".$num_values." values and ".$iterations." loop iterations";
print "\n";

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if ($var != 'test0' &&
        $var != 'test1' &&
        // ...
        // yes I really have 1000 lines in my file
        // ...
        $var != 'test999') {}
}
print "\nCase 1: plain comparison";
print "\nTime 1: ". (microtime(true) - $start);
print "\n";

$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
    $array1[] = 'test'.$i;
}
for($i = 0; $i < $iterations; ++$i) {
    if (!in_array($var, $array1) ) {}
}
print "\nCase 2: in_array comparison";
print "\nTime 2: ".(microtime(true) - $start);
print "\n";

$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
    $array2['test'.$i] = 1;
}
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array2[$var])) {}
}
print "\nCase 3: values as keys, isset comparison";
print "\nTime 3: ".(microtime(true) - $start);
print "\n";

$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
    $array3['test'.$i] = 1;
}
for($i = 0; $i < $iterations; ++$i) {
    if (!array_key_exists($var, $array3)) {}
}
print "\nCase 4: values as keys, array_key_exists comparison";
print "\nTime 4: ".(microtime(true) - $start);
print "\n";

نتائجي (PHP 5.5.9):

Case 1: plain comparison
Time 1: 31.616894006729

Case 2: in_array comparison
Time 2: 23.226133823395

Case 3: values as keys, isset comparison
Time 3: 0.050863981246948

Case 4: values as keys, array_key_exists comparison
Time 4: 0.13700890541077

أوافق على أن هذا متطرف بعض الشيء ولكنه يظهر الصورة الكبيرة والإمكانات الكبيرة في المصفوفات الترابطية الشبيهة بجدول التجزئة في PHP، ما عليك سوى استخدامها

لاحظ أنه أشار RoBorg بها، هناك النفقات العامة في خلق مجموعة لذلك يجب أن يتم نقل داخل حلقة التكرار. لهذا السبب، آخر Sparr هي أيضا مضللة بعض الشيء كما أن هناك من النفقات العامة مع وظيفة array_flip.

وهنا مثال آخر مع كل الاختلافات 5:

$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
   if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
print "Time1: ". (microtime(true) - $start);

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
   if (!in_array($var, $array) ) {}
}
print "Time2: ".(microtime(true) - $start);

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
   if (!in_array($var, array('test1', 'test2', 'test3', 'test4')) ) {}
}
print "Time2a: ".(microtime(true) - $start);

$array2 = array_flip($array);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
  if (!isset($array2[$var])) {}
}
print "Time3: ".(microtime(true) - $start);

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    $array2 = array_flip($array);
  if (!isset($array2[$var])) {}
}
print "Time3a: ".(microtime(true) - $start);

ونتائجي:

Time1 : 0.59490108493 // straight comparison
Time2 : 0.83790588378 // array() outside loop - not accurate
Time2a: 2.16737604141 // array() inside loop
Time3 : 0.16908097267 // array_flip outside loop - not accurate
Time3a: 1.57209014893 // array_flip inside loop

في ملخص، وذلك باستخدام array_flip (مع isset) أسرع من inarray ولكن ليس بالسرعة المقارنة المباشرة.

عند الحديث عن PHP، والسؤال عما إذا كان:

  • مجموعة من "if" و"else ifs" ،
  • "إذا" مع مجموعة من الشروط "أو" (كما في تفاصيل المنشور الأصلي)، أو
  • استخدام "in_array" مع مصفوفة تم إنشاؤها أثناء التنقل،

أفضل،

يجب على المرء أن يضع في اعتباره أن عبارة "switch" الخاصة بلغة PHP هي بديل مصمم لمثل هذه المواقف وقد تكون إجابة أفضل.(على الرغم من أن مثال الملصق يقودنا إلى مقارنة حلين فقط، إلا أن عنوان السؤال الفعلي يطلب مراعاة عبارات in_array مقابل عبارات PHP، لذلك أعتقد أن هذه لعبة عادلة).

في مثال الملصق، أوصي بدلاً من ذلك بما يلي:

switch ($var)
{ case 'test1': case 'test2': case 'test3': case 'test4':
     echo "We have a good value"; break;
  default:
     echo "We do not have a good value";
}

أتمنى أن تسمح PHP ببعض التركيبات غير البدائية في الحالات، مثل الفاصلة لـ "أو".لكن ما سبق هو ما اعتبره مصممو PHP أوضح طريقة للتعامل مع هذا الأمر.ويبدو أنه أكثر كفاءة في وقت التنفيذ من البديلين الآخرين أيضًا.

طالما أنني أتحدث عن قائمة الرغبات، فإن "IN" الموجود في SQL سيكون أكثر وضوحًا بالنسبة لمثال الملصق.

ربما يكون هذا التفكير هو ما يؤدي إلى رغبة الأشخاص في استخدام "in_array" لمثل هذه المواقف، ولكن من المؤسف نوعًا ما أن تضطر إلى إنشاء بنية بيانات ثم استخدام مسند مصمم لبنية البيانات هذه، بدلاً من وجود طريقة فقط قل ذلك دون حدوث ذلك.

هنا تحديث مباشر لهذا المقعد مع حالة أخرى https://3v4l.org/OA2S7

نتائج PHP 7.3:

  • مقارنات متعددة: 0.057507991790771

  • in_array: 0.02568507194519

  • array_flip() قياس الحلقة الخارجية + isset(): 0.014678001403809

  • لم يتم قياس الحلقة الخارجية array_flip() + isset(): 0.015650033950806

  • البحث والمقارنة: 0.062782049179077

أعلم أن عمر هذا السؤال ما يقرب من 10 سنوات، ولكن هناك طرق أخرى للقيام بذلك.لقد استخدمت الطريقة B من صفحة نيك مع الآلاف من الإدخالات.لقد كان سريعًا بشكل لا يصدق.

foreach(array_values($haystack) as $v)
    $new_haystack[$v] = 1; 
}

// So haystack becomes:
$arr[“String1”] = 1;
$arr[“String2”] = 1;
$arr[“String3”] = 1;


// Then check for the key:
if (isset($haystack[$needle])) {
    echo("needle ".$needle." found in haystack");
}

وبلدي اختبار

$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
$end = microtime(true);

print "Time1: ". ($end - $start)."<br />";

$start2 = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!in_array($var, $array) ) {}
}
$end2 = microtime(true);

print "Time2: ".($end2 - $start2)."<br />";

$array_flip = array_flip($array);

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array_flip[$var])) {}
}
$end = microtime(true);
print "Time3: ".($end - $start)."<br />";

$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
    if (!isset($array[$var])) {}
}
$end = microtime(true);

print "Time4: ". ($end - $start)."<br />";
<اقتباس فقرة>   

وTIME1: 0.20001101493835

     

وTIME2: 0.32601881027222

     

وTime3: ،072004079818726

     

وTime4: ،070003986358643

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top