2012-03-27 17 views
314

के लिए ब्रेक के बिना सरणी के माध्यम से लूपिंग और आइटम को हटाने के बाद, मेरे पास लूप के लिए निम्न है, और जब मैं किसी आइटम को निकालने के लिए splice() का उपयोग करता हूं, तो मुझे लगता है कि 'सेकंड' अपरिभाषित है। मैं जांच सकता हूं कि यह अपरिभाषित है, लेकिन मुझे लगता है कि ऐसा करने के लिए शायद एक और शानदार तरीका है। इच्छा है कि किसी आइटम को आसानी से हटाएं और आगे बढ़ें।लूप

for (i = 0, len = Auction.auctions.length; i < len; i++) { 
    auction = Auction.auctions[i]; 
    Auction.auctions[i]['seconds'] --; 
    if (auction.seconds < 0) { 
     Auction.auctions.splice(i, 1); 
    }   
} 
+6

पीछे की ओर इशारा करने और लंबाई समायोजित करने के अलावा, आप केवल उन सदस्यों को भी डाल सकते हैं जिन्हें आप एक नई सरणी में चाहते हैं। – RobG

उत्तर

630

जब आप .splice() करते हैं तो सरणी को फिर से अनुक्रमित किया जा रहा है, जिसका अर्थ है कि जब आप हटा दिए जाते हैं तो आप एक इंडेक्स पर छोड़ देंगे, और आपके कैश किए गए .length अप्रचलित हैं।

इसे ठीक करने के लिए, आप या तो एक .splice() के बाद i घटती करने, या बस रिवर्स में पुनरावृति आवश्यकता होगी ...

var i = Auction.auctions.length 
while (i--) { 
    ... 
    if (...) { 
     Auction.auctions.splice(i, 1); 
    } 
} 

इस तरह फिर से अनुक्रमण में अगले आइटम को प्रभावित नहीं करता पुनरावृत्ति, चूंकि अनुक्रमण केवल वर्तमान बिंदु से वस्तुओं को ऐरे के अंत तक प्रभावित करता है, और पुनरावृत्ति में अगला आइटम वर्तमान बिंदु से कम है।

+1

मुझे सबसे अच्छा समाधान की तरह लग रहा है। और सबसे तेज़, वैसे भी। –

+1

अच्छा! यह एक समुदाय विकी बीटीडब्ल्यू क्यों है? – 0xc0de

+0

ब्याज से, यह समाधान संभवतः काम नहीं करेगा अगर सरणी उन कार्यों की एक सरणी थी जिसे आप फिर से चालू करना चाहते थे और क्रम में इन्हें सरणी में जोड़ा गया था, उदाहरण के लिए? – ComethTheNerd

34

लंबाई हर बार लूप के माध्यम से करने के बजाय सिर्फ शुरू में, उदा, इस तरह आप सीमा से अधिक नहीं होगा पुनः गणना करें, .:

for (i = 0; i < Auction.auctions.length; i++) { 
     auction = Auction.auctions[i]; 
     Auction.auctions[i]['seconds'] --; 
     if (auction.seconds < 0) { 
      Auction.auctions.splice(i, 1); 
      i--; //decrement 
     } 
} 

संपादित करें: यदि कथन में कमी शामिल है।

+7

मुझे लगता है कि सरणी के माध्यम से पीछे की तरफ जाना आसान है, तो आपको लंबाई को समायोजित करने की आवश्यकता नहीं है। – RobG

+4

मैंने लूप में स्प्लिसिंग के बाद सरणी की लंबाई को फिर से गणना करने से भी अनदेखा किया। मजेदार कैसे कुछ आसान इतना हमें एक पल के लिए हमारे सिर खरोंच कर सकते हैं। –

18

हालांकि अपने प्रश्न सरणी पर दोहराया जा रहा है और नहीं के बारे में तत्वों (अलावा कुछ अन्य प्रसंस्करण के लिए) को बाहर निकालने कुशलता से तत्वों को हटाने के बारे में है, मुझे लगता है कि एक ऐसी ही स्थिति में अगर यह पर पुनर्विचार करना चाहिए।

इस दृष्टिकोण की एल्गोरिदमिक जटिलता O(n^2) स्प्लिस फ़ंक्शन के रूप में है और लूप के लिए दोनों सरणी पर पुनरावृत्ति (स्प्लिस फ़ंक्शन सबसे खराब मामले में सरणी के सभी तत्वों को स्थानांतरित करता है)। इसके बजाय आप केवल आवश्यक तत्वों को नए सरणी में धक्का दे सकते हैं और फिर उस सरणी को वांछित चर (जिसे केवल पुनरावृत्त किया गया था) पर असाइन करें।

var newArray = []; 
for (var i = 0, len = Auction.auctions.length; i < len; i++) { 
    auction = Auction.auctions[i]; 
    auction.seconds--; 
    if (!auction.seconds < 0) { 
     newArray.push(auction); 
    } 
} 
Auction.auctions = newArray; 

या सरणी कार्य करता है और तीर फ़ंक्शन का उपयोग एक लाइन पर यह सब फिट करने के लिए:

Auction.auctions = Auction.auctions.filter(auction => --auction.seconds >=0); 
+1

मुझे लगता है कि आपकी विधि सबसे सुरक्षित है, क्योंकि यह एक नई सरणी बनाता है, हमें इसके लिए() इंडेक्स "ब्रेक" के बारे में चिंता करने की ज़रूरत नहीं है। नए ब्राउज़र के साथ, हालांकि हम इसके बजाय 'Array.filter()' फ़ंक्शन का उपयोग कर सकते हैं: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter –

+0

ध्यान दें कि यहां फ़िल्टर संस्करण लूप संस्करण की तरह प्रत्येक नीलामी पर सेकंड कम नहीं करता है! – nus

+0

क्या किसी के पास 'फ़िल्टर' बनाम पीछे की तरफ +' splice' का उपयोग करने पर बेंचमार्क है? – qxz

13
Auction.auction = Auction.auctions.filter(function(el) { 
    return --el["seconds"] > 0; 
}); 
+0

यह एक अच्छी विधि है, जैसा ऊपर 0xc0de। केवल समस्या, इसे आईई 9 + में लागू किया गया था ... इसलिए पिछड़ा संगत नहीं। –

+5

@AlexisWilke: सौभाग्य से, हम भविष्य में अब हैं, और आईई 8 और उसके पूर्ववर्तियों की कब्रों पर नृत्य कर सकते हैं। –

78

यह एक बहुत आम मुद्दा है। समाधान पीछे की ओर पाश के लिए है:

for (var i = Auction.auctions.length - 1; i >= 0; i--) { 
    Auction.auctions[i].seconds--; 
    if (Auction.auctions[i].seconds < 0) { 
     Auction.auctions.splice(i, 1); 
    } 
} 

अगर आप उन्हें अंत के बंद पॉपिंग रहे हैं, क्योंकि सूचकांक संरक्षित किया जाएगा के रूप में आप पीछे की ओर जाना यह कोई फर्क नहीं पड़ता।

0

जब पाशन newArray में एक सरणी रिले करने का प्रयास करें:

var auctions = Auction.auctions; 
var auctionIndex; 
var auction; 
var newAuctions = []; 

for (
    auctionIndex = 0; 
    auctionIndex < Auction.auctions.length; 
    auctionIndex++) { 

    auction = auctions[auctionIndex]; 

    if (auction.seconds >= 0) { 
    newAuctions.push(
     auction); 
    }  
} 

Auction.auctions = newAuctions; 
8

यहाँ जोड़ के समुचित उपयोग के लिए एक और उदाहरण है। यह उदाहरण 'सरणी' से 'विशेषता' को हटाने के बारे में है।

for (var i = array.length; i--;) { 
    if (array[i] === 'attribute') { 
     array.splice(i, 1); 
    } 
} 
+0

उस सरणी नहीं होना चाहिए। लम्बाई -1? – Izzy

+0

मुझे नहीं लगता क्योंकि 'i - 'सूचकांक को कम करता है। यदि आप 'सरणी करते हैं।लंबाई -1' तो 'सरणी' का अंतिम तत्व –

+1

छोड़ दिया जाएगा, मैं देखता हूं, लेकिन मुझे थोड़ा तर्क देना चाहिए कि यह इतना पठनीय नहीं है। यहां तक ​​कि मैं शुरुआती नहीं हूं, पहली नज़र में मैंने यह भी नहीं देखा कि लूप के चेक ब्लॉक के अंदर आप 'i' कमी करते हैं। 'के लिए (var i = array.length-1; i> = 0; i--)' बहुत अधिक क्लीनर है (और यह समान प्रभाव उत्पन्न करता है) – Izzy

8

एक और सरल उपाय एक बार एक सरणी तत्वों को पचाने के लिए:

while(Auction.auctions.length){ 
    // From first to last... 
    var auction = Auction.auctions.shift(); 
    // From last to first... 
    var auction = Auction.auctions.pop(); 

    // Do stuff with auction 
} 
1
for (i = 0, len = Auction.auctions.length; i < len; i++) { 
    auction = Auction.auctions[i]; 
    Auction.auctions[i]['seconds'] --; 
    if (auction.seconds < 0) { 
     Auction.auctions.splice(i, 1); 
     i--; 
     len--; 
    } 
} 
+3

ए ** अच्छा उत्तर ** हमेशा क्या किया गया था इसका स्पष्टीकरण होगा और यह क्यों न केवल ओपी के लिए बल्कि भविष्य के आगंतुकों के लिए ऐसा किया गया था। –

0

तुम बस के माध्यम से देखने के लिए और shift()

+2

कृपया इस विधि का उपयोग कर एक उदाहरण जोड़ें। – Ivan

1

का उपयोग आप उपयोग कर ES6 + ई कर रहे हैं कर सकते हैं - क्यों सिर्फ का उपयोग नहीं Array.filter विधि?

Auction.auctions = Auction.auctions.filter((auction) => { 
    auction['seconds'] --; 
    return (auction.seconds > 0) 
}) 

ध्यान दें कि फिल्टर यात्रा के दौरान सरणी तत्व को संशोधित केवल वस्तुओं के लिए काम करता है और आदिम मूल्यों की सरणी के लिए काम नहीं करेगा।