2009-12-21 17 views
13

एक बड़े सरणी से प्रत्येक nth आइटम का चयन करने के लिए सबसे अधिक कुशल तरीका क्या होगा? क्या ऐसा करने का एक 'स्मार्ट' तरीका है या एकमात्र रास्ता लूप कर रहा है?एक सरणी से प्रत्येक nth आइटम का चयन

कुछ बिंदुओं पर विचार करने के

:

  • सरणी
  • 130 000 आइटम के साथ काफी बड़ी है मैं हर 205 वां आइटम
  • आइटम संख्यानुसार अनुक्रमित नहीं कर रहे हैं का चयन करने के लिए है, इसलिए for($i = 0; $i <= 130000; $i += 205) काम नहीं करेगा

    :

अब तक, इस लिए सबसे कारगर विधि मैं के साथ आ गया है

या सापेक्ष के साथ एक ही:

$result = array(); 
$i = 0; 
foreach($source as $value) { 
    if($i % 205 == 0) { 
     $result[] = $value; 
    } 
    $i++; 
} 

इन विधियों काफी धीमी गति से हो सकता है, वहाँ सुधार करने के लिए किसी भी तरह से है? या मैं बस यहाँ बाल बांट रहा हूँ?

उचित स्पष्टीकरण के साथ संपादित करें

अच्छा जवाब चारों ओर, स्वीकार किए जाते हैं जवाब के रूप में सबसे फिटिंग लेने की कोशिश की। धन्यवाद!

+0

यह मुझे उचित लगता है - क्या आप वाकई बाधा उत्पन्न कर रहे हैं? यदि नहीं, तो इसे देखने के लिए प्रोफाइल! इसमें कितना समय लगता है? –

+0

@ डोमिनिक, यह एक बाधा का इतना अधिक नहीं है, केवल एक दिलचस्प समस्या है जिसके लिए मुझे उचित समाधान नहीं मिला। ऐसा मत सोचें कि 'सही' उत्तर निष्पादन समय के कुछ मिलीसेकंड से अधिक दाढ़ी देगा, लेकिन यह जानना अच्छा लगेगा। :) –

उत्तर

13

एक foreach पाश अपने बड़े तुलना परीक्षण पर आधारित सरणी पर सबसे तेजी से यात्रा प्रदान करता है। जब तक कोई लूप अनलोलिंग के साथ समस्या को हल करने की इच्छा नहीं रखता है, तो मैं आपके जैसा कुछ भी पसंद करूंगा।

यह उत्तर तेज़ी से चलना चाहिए।

$result = array(); 
$i = 0; 
foreach($source as $value) { 
    if ($i++ % 205 == 0) { 
     $result[] = $value; 
    } 
} 

मैं परीक्षण करने के लिए समय नहीं है, लेकिन आप @ हैम के समाधान अगर आप पहले संख्यानुसार सूचकांक सरणी की भिन्नता उपयोग करने में सक्षम हो सकता है।

$result = array(); 
$source = array_values($source); 
$count = count($source); 
for($i = 0; $i < $count; $i += 205) { 
    $result[] = $source[$i]; 
} 

यह काफी हद तक कैसे समारोह array_values ​​अनुकूलित पर निर्भर करेगा है: यह आप मेरे पिछले समाधान पर कोई लाभ प्राप्त कर सकते हैं देखने के लिए कोशिश कर रहा लायक है। यह बहुत अच्छी तरह से प्रदर्शन कर सकता है।

+0

महान स्पष्टीकरण और वास्तव में जो करने की कोशिश की गई, उसे पूरा करने का एक तेज़ तरीका (बस मामूली, लेकिन वैसे भी तेज़)। धन्यवाद! –

+0

@Tatu, array_push पर एक त्वरित तुलना परीक्षण के बाद और [] 200,000 वस्तुओं की एक परीक्षण सरणी पर मैंने पाया [] को दो गुना तेजी से चलाने के लिए मिला। मैंने अपना जवाब संशोधित किया और मैं असाइनमेंट का उपयोग करने का सुझाव देता हूं जिस तरह से आपने शुरुआत की थी। –

+1

@ टाटू, मैंने उपरोक्त दो विधियों को तुरंत बेंचमार्क किया और दूसरा प्रारंभिक सरणी 50,000 से अधिक परिणामों के औसत पर होने पर तेज हो गई। मेरे पास केवल array_fill() और श्रेणी() द्वारा उत्पन्न संख्यात्मक रूप से अनुक्रमित सरणी के साथ शुरू करने का परीक्षण करने का समय था। –

6

मैं array_slice

$count = count($array) ; 
for($i=205;$i<$count;$i+=205){ 
    $result[] = array_slice($array,$i,1); 
} 

का उपयोग कर अपने सरणी संख्यानुसार अनुक्रमित किया गया था करने के लिए सलाह देते हैं, यह बहुत तेजी से होगा:

$count = count($array) ; 
for($i=205;$i<$count;$i+=205){ 
    $result[] = $array[$i]; 
} 
+1

कम से कम वाक्यविन्यास बहुत स्पष्ट है, क्या कोई विचार वास्तव में प्रदर्शन में सुधार करेगा? –

+1

लूप धीमे हैं। आपकी गिनती() भी हास्यास्पद रूप से धीमी है। –

+0

लूप से गिनती लेना वास्तव में इसे काफी हद तक गति देगा। –

0

आप सरणी सूचक स्थानांतरित नहीं कर सकते, ऐसा लगता है, की तुलना में अधिक एक बार में एक बार। मैं व्यक्तिगत रूप से इस का प्रयोग करेंगे: किसी को एक समारोह है कि एक समय में केवल एक चरण से सरणी सूचक अधिक स्थानांतरित कर सकते हैं पा सकते हैं

reset($source); 
$next = true; 
while($next === true){ 
    $result[] = current($source); 
    for(i=0;i<205;i++){ 
     $next = next($source); 
    } 
} 

हैं, तो आप एक बेहतर जवाब होगा। मुझे लगता है कि यह अच्छा है हालांकि।

+0

आप सही हैं, एक समय में पॉइंटर 205 पदों को स्थानांतरित करना समाधान होगा, अन्यथा ये सभी अलग-अलग वाक्यविन्यास के साथ एक ही चीज़ हैं, मुझे लगता है। –

+1

मेरा जवाब देखें। ArrayIterator :: खोज – Gordon

+0

स्थिति में पॉइंटर को स्थानांतरित कर सकता है क्या होगा यदि ऐसे मान हैं जो * सत्य * का मूल्यांकन नहीं करते हैं? – Gumbo

7

एक का उपयोग कर नई Spl datastructures सादा सरणियों का उपयोग करने से बेहतर परिणाम हो सकता है ArrayIterator::seek()

भी प्रयास करें।

+0

देखेंगे, केवल कारण यह है कि मैंने इसे स्वीकार नहीं किया क्योंकि सही जवाब यह था कि मुझे अपना बदलना होगा कोडबेज महत्वपूर्ण रूप से ArrayObjects का समर्थन करने के लिए महत्वपूर्ण है। लेकिन ध्यान दिया और plussed। –

1

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

संपादित करें: या केवल 205 वें आइटम के साथ एक अलग सरणी बनाएं और बनाए रखें (जो सम्मिलित या उस तरह कुछ अपडेट हो जाता है)।

-1

आप केवल array_keys का उपयोग केवल सरणी कुंजी पर काम करने के लिए कर सकते हैं।

$keys = array_keys($array); 
for ($i=0, $n=min(count($keys), 130000); $i<$n; $i += 205) { 
    $result[] = $array[$keys[$i]]; 
} 
+3

यदि सरणी ट्रैवर्सल एक बाधा है, तो सभी चाबियों की पुनर्प्राप्ति नहीं होगी? – xtofl

+0

@xtofl: PHP में Arrays अन्य भाषाओं में कोई असली सरणी नहीं हैं। वे एक हैश टेबल के साथ लागू किया जाता है। और चाबियां अलग-अलग संग्रहित होती हैं, शायद एक लिंक्ड सूची में। – Gumbo

2

मुझे लगता है कि इस समस्या का समाधान किसी भी PHP वाक्यविन्यास में नहीं है बल्कि आपके कोड के डिज़ाइन में है।

आप या तो सरणी संख्यात्मक रूप से अनुक्रमित कर सकते हैं (शायद आपके आवेदन के लिए व्यवहार्य नहीं हो सकता है), प्रत्येक 205 वें आइटम का ट्रैक रखें, या केवल एक बार सरणी को खोजें (प्रत्येक 205 वें आइटम की सूची कैश करें)।

मेरे दिमाग में, प्रत्येक 205 वें आइटम का ट्रैक रखने के लिए लागू करना आसान होगा। आप बस डेटाबेस या किसी चीज़ में सभी वस्तुओं की गिनती रखेंगे, और जब भी कोई आइटम जोड़ा जाता है, तो गिनती के मॉड्यूल की जांच करें। यदि आपके पास 205 वां आइटम है, तो उसे सरणी में जोड़ें। जब आइटम हटा दिए जाते हैं, तो यह मुश्किल होगा। आपको अपने सभी 205 वें आइटम को रीयलिन करने के लिए संपूर्ण सरणी को दोबारा जांचना पड़ सकता है।

ऐसा करना आसान होगा यदि आप हटाए गए आइटम पर शुरू कर सकते हैं और आगे बढ़ सकते हैं, लेकिन फिर यह केवल संख्यात्मक रूप से अनुक्रमित सरणी के लिए काम करेगा - और यदि यह सत्य था, तो आपको आगे बढ़ना नहीं होगा, आप इसे फिर से समझने के लिए थोड़ा सा गणित करेंगे।

  • संख्यात्मक अनुक्रमित - बेहतर दीर्घकालिक समाधान है लेकिन बहुत कठिन
  • रखते हुए ट्रैक लागू करने के लिए - आसान लागू करने के लिए, लेकिन आप फिर से गंदे पाने के लिए जब आप आइटम
  • कैशिंग आइटम हटा देते होगा - आपको शायद इसे अन्य दो समाधानों के लिए भी करना चाहिए, लेकिन अपने आप पर, यह तब तक तेज होगा जब तक कि सरणी संशोधित न हो जाए, उस स्थिति में आपको शायद इसे फिर से करना होगा।
0
  • एक दो आयामी सरणी बनाएं [205] [एन]
  • सरणी में लोड डेटा
  • पहुँच 205 वां तत्व हर एन

लग सकता है के लिए मूर्खतापूर्ण लेकिन परिभाषा के द्वारा यह सबसे तेज है चूंकि आप सीधे मेमोरी स्थानों तक पहुंचते हैं और कोई तुलना नहीं करते हैं।

संबंधित मुद्दे