2008-11-27 7 views
15

क्या यह निम्न करने के लिए तेज़ है:जो तेज़ है: in_array() या PHP में अभिव्यक्ति का एक गुच्छा?

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

या:

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

क्या ऐसे कई मूल्य हैं जिन पर यह एक या दूसरे को करने के लिए तेज़ है?

(इस मामले में, दूसरे विकल्प में उपयोग की जाने वाली सरणी मौजूद नहीं है।)

+0

विषय बंद थोड़ा - क्या आपने कुछ मिनट पहले ही अपना अन्य प्रश्न हटा दिया था, या क्या मैं पागल हो रहा हूं? – Greg

उत्तर

14

मैं दृढ़ता से सिर्फ 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 

थोड़ा तुच्छ टिप्पणी के लिए देखने के लिए, विधि 1 अधिक समय लगता है, तो $var सेट नहीं है, (पर निर्भर करता है कि कितने की स्थिति आप परीक्षण)

+0

PHP का कौन सा संस्करण आप पर हैं? 5.2.6 (विंडोज़) समय 1 देता है: 1.36 समय 2: 4.88 - यह एक बड़ा अंतर है – Greg

+1

इसके अलावा आप लूप के बाहर सरणी (...) को लेकर थोड़ा धोखा दे रहे हैं - यदि आप इसे सवाल के रूप में उपयोग करते हैं, मेरा टाइम 2 6 सेकंड से अधिक – Greg

+0

5.2.5 (मैक ओएस एक्स) पर जाता है, मुझे गैर-धोखाधड़ी संस्करण – Owen

5

पहला तेज होगा - दूसरे में बहुत अधिक ओवरहेड है: सरणी बनाना, फ़ंक्शन को कॉल करना, सरणी खोजना ...

हालांकि, जैसा कि मैंने एक प्रश्न में कहा है कि कुछ जवाब नीचे हैं, समयपूर्व अनुकूलन है सब बुराई की जड़। आपको अपना कोड पठनीय होने के लिए लिखना चाहिए, फिर यदि पर इसे अनुकूलित अनुकूलित करने की आवश्यकता है, तो अनुकूलित करें।

संपादित करें:

@ ओवेन का कोड (PHP 5.2.6/विंडोज़) के साथ मेरा समय:

Time1: 1.33601498604 
Time2: 4.9349629879 

सरणी (...) लूप के अंदर आगे बढ़ते, प्रश्न में के रूप में:

Time1: 1.34736609459 
Time2: 6.29464697838 
+0

विचित्र :( – Owen

+0

ओह को साफ़ करने के लिए कुछ होना चाहिए ओह, आपका नाम टाइप करने के लिए खेद है ओवेन! – Greg

2

in_array बड़ी संख्या में वस्तुओं के लिए तेज़ होगा। डेटा और आपके कंप्यूटर से संबंधित कई कारकों के आधार पर "बड़ा" बहुत ही व्यक्तिपरक है। चूंकि आप पूछ रहे हैं, मुझे लगता है कि आप वस्तुओं की एक छोटी संख्या से निपट नहीं रहे हैं। लंबी सूचियों के लिए, this information पर ध्यान दें, और फ़्लिप किए गए सरणी के साथ प्रदर्शन को मापें ताकि PHP रैखिक खोज के बजाय हैश लुकअप का उपयोग कर सके। एक "स्थैतिक" सरणी के लिए जो ट्विक प्रदर्शन में सुधार नहीं कर सकता है, लेकिन यह भी हो सकता है।

एक फ़्लिप सरणी और अधिक संगत परिणाम के लिए और अधिक पुनरावृत्तियों साथ ओवेन का परीक्षण कोड, का उपयोग करना:

$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 
+0

छोटी टिप्पणी: एक बड़ी सरणी coul flipping डी बहुत मेमोरी का उपयोग करें। –

+1

सरणी फ़्लिप किए गए कॉन्फ़िगरेशन में घोषित किया जा सकता है – Sparr

6

ध्यान दें कि आप !== बयान के एक झुंड को बदलने के लिए देख रहे हैं, तो आप के लिए तीसरे पैरामीटर पास करना चाहिए in_arraytrue के रूप में, जो सरणी में आइटमों पर प्रकार की जांच लागू करता है।

सामान्य != इसकी आवश्यकता नहीं है, जाहिर है।

1

ध्यान दें कि RoBorg ने बताया कि सरणी बनाने में ओवरहेड है इसलिए इसे पुनरावृत्ति पाश के अंदर ले जाना चाहिए। इस कारण से, स्पायर की पोस्ट भी थोड़ा भ्रामक है क्योंकि array_flip फ़ंक्शन के साथ ओवरहेड है।

$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); 

मेरे परिणाम:

यहाँ सब 5 बदलाव के साथ एक और उदाहरण

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 की तुलना में तेजी है, लेकिन के रूप में तेजी से नहीं एक सीधी तुलना के रूप में ।

+0

लूप में सरणी फ़्लिप न करें। इसे $ array2 = array ('test1' => 0, 'test2' => 0, 'test3' => 0, 'test4' => 0) में बदलें; और फिर प्रयत्न करें। पहले मामले में सरणी का निर्माण किया गया है इसलिए इस मामले में आपको सरणी भी बनाना चाहिए। उपर्युक्त टिप्पणी पर – jmucchiello

+0

, जारीकर्ता वैल के रूप में 0 पर झूठी वापसी करेगा, वैल के रूप में 1 का उपयोग करने के लिए बेहतर होगा या array_key_exists का उपयोग करें – Jason

1

हाय मैंने अभी इस मामले को चरम सीमा तक ले लिया और बताया कि मूल्यों की बढ़ती संख्या के साथ सादा तुलना सबसे अधिक प्रभावी तरीका नहीं है।

$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 

मैं मानता हूँ, एक छोटे से चरम thats लेकिन यह बड़ी तस्वीर और में काफी संभावना से पता चलता PHP की हैश-टेबल जैसी एसोसिएटिव सरणी, आपको बस इसका उपयोग करना होगा

1

PHP की बात करते समय, और पूछें कि:

  • का एक सेट "अगर" s और "और भारतीय विदेश सेवा",
  • एक "अगर" "या" एड की स्थिति का एक सेट (मूल पोस्ट विवरण के रूप में), या
  • "in_array के उपयोग के साथ "एक पर-फ्लाई निर्माण सरणी के साथ,

बेहतर है,

एक है कि PHP भाषा ध्यान में रखना चाहिए" स्विच "बयान ऐसी स्थितियों के लिए बनाया गया एक विकल्प है और एक बेहतर जवाब हो सकता है । (हालांकि पोस्टर का उदाहरण हमें दो समाधानों की तुलना करने के लिए प्रेरित करता है, वास्तविक प्रश्न शीर्षक में PHP विवरणों के विरुद्ध in_array पर विचार करने के लिए कहा जाता है, इसलिए मुझे लगता है कि यह उचित खेल है)।

पोस्टर के उदाहरण में, तो, मैं बजाय सिफारिश करेंगे: इस तरह के लिए "या" एक अल्पविराम के रूप में

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 के डिजाइनरों को इसे संभालने का सबसे स्पष्ट तरीका माना जाता है। और यह अन्य दो विकल्पों की तुलना में निष्पादन समय पर अधिक कुशल प्रतीत होता है।

जब तक मैं एक इच्छा सूची के बारे में बात कर रहा हूं, एसक्यूएल में पाया गया "आईएन" पोस्टर की उदाहरण स्थिति के लिए भी स्पष्ट होगा।

यह सोच शायद ऐसी परिस्थितियों के लिए "in_array" का उपयोग करने वाले लोगों की ओर ले जाती है, लेकिन डेटा संरचना बनाने के लिए यह दुर्भाग्यपूर्ण है और फिर उस डेटा संरचना के लिए डिज़ाइन की गई भविष्यवाणी का उपयोग करें उस ओवरहेड के बिना बस इसे कहने का एक तरीका।

0

मुझे पता है कि यह प्रश्न लगभग 10 वर्ष पुराना है, लेकिन ऐसा करने के अन्य तरीके भी हैं। मैंने हजारों प्रविष्टियों के साथ Nick's page से विधि बी का उपयोग किया। यह अविश्वसनीय रूप से तेज़ था।

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"); 
} 
संबंधित मुद्दे