2010-06-09 12 views
6

Possible Duplicates:
Exception during iteration on collection and remove items from that collection
How to remove elements from a generic list while iterating around it?
Better way to remove matched items from a listकैसे ठीक सूची से आइटम को हटा दें

// tmpClientList is List<Client> type 

if (txtboxClientName.Text != "") 
    foreach (Client cli in tmpClientList) 
     if (cli.Name != txtboxClientName.Text) 
      tmpClientList.Remove(cli); 

त्रुटि: "। संग्रह संशोधित किया गया था; गणन किए गए कार्य पूरे नहीं हो सकता है"

किसी अन्य सूची या सरणी में इन आइटम्स की अनुक्रमणिका सहेजने के बिना, और कोड में किसी अन्य स्थान पर उन्हें हटाने के बिना, मैं कुछ सरल तरीके से सूची से आइटम कैसे हटा सकता हूं। RemoveAt (अनुक्रमणिका) भी कोशिश की लेकिन यह वही स्थिति है, जब लूप चलाता है तो संशोधित होता है।

+0

सटीक डुप्लिकेट मुद्दों पर सहमति हुई, लिंक देखें http://stackoverflow.com/questions/1154325/better-way-to-remove-matched-items-from-a-list और लिंक दो: http: //stackoverflow.com/questions/1541777/can-you-remove-an-item-from-a-list-whilst-iterating-through-it-in-c – CrimsonX

उत्तर

1

समस्या यह है कि आप किसी फ़ोरैच पुनरावृत्ति में सूची को संशोधित करने का प्रयास कर रहे हैं। इसे एक के साथ बदलें और आपको ठीक होना चाहिए।

इसके अलावा, चूंकि आप नाम के लिए उपयोगकर्ता इनपुट का उपयोग कर रहे हैं, इसलिए अतिरिक्त सफेद रिक्त स्थान को निकालने के लिए कम से कम एक ट्रिम() के साथ इनपुट को साफ करने पर विचार करें। यदि आप नहीं करते हैं, तो 'जॉन' और 'जॉन' दो अलग-अलग चीजें होंगी। प्रारंभिक के लिए वही! = "" जांचें।

+0

आपका मतलब है, कि "" और "" वही, और मुझे उस स्थिति में भी इनपुट को ट्रिम करना चाहिए (जब उपयोगकर्ता इनपुट के रूप में केवल सफेद वर्ण टाइप करता है)? – qlf00n

+0

@dygi: हाँ। सफेद रिक्त स्थान को हटाने से केवल प्रासंगिक जानकारी होती है - जो इस मामले में कोई नहीं है। किसी मामले के लिए जब ऐसा हो सकता है: उपयोगकर्ता नाम टाइप करना शुरू कर देता है, इसके बाद एक स्थान समेत, फिर वर्णों और अंतरिक्ष को हटाने का निर्णय लेता है, क्योंकि वह इसे 'देख' नहीं सकता है। – Rox

2

foreach का उपयोग न करें। RemoveAt का उपयोग करके, सूची के लिए उपयोग करें और नीचे उतरें (यानी अंत से शुरू करें)।

तो,

// tmpClientList is List<Client> type 

if (txtboxClientName.Text != "") 
    foreach (int pos = tmpClientList.Length - 1; pos >= 0; pos--) 
    { 
     Client cli = tmpClientList[pos]; 
     if (cli.Name != txtboxClientName.Text) 
      tmpClientList.RemoveAt(pos); 
    } 
4

या तो एक के लिए/जबकि पाश, या tmpClientList.RemoveAll(a => a.Name == txtboxClientName.Text) का उपयोग करें। जैसा कि आपने निर्दिष्ट नहीं किया है कि आप किस सी # संस्करण का उपयोग कर रहे हैं, ymmw।

+1

और जब 2.0 तक सीमित है, तो यह थोड़ा और अधिक वर्बोज़ है: 'tmpClientList.RemoveAll (प्रतिनिधि (क्लाइंट ए) {वापसी a.Name == txtboxClientName.Text;}); – Humberto

11

सूची के माध्यम से पीछे की ओर जाएं .. इस तरह से किसी आइटम को हटाने से अगले आइटम को प्रभावित नहीं होता है।

for(var i=tmpClientList.Count-1;i>=0;i--) 
{ 
    if (tmpClientList[i].Name != txtboxClientName.Text) 
      tmpClientList.RemoveAt(i); 

} 
+0

अच्छा सरल समाधान, – qlf00n

11

एक List<T> पर, एक RemoveAll विधि उस वस्तु को निकालना है कि क्या इंगित करने के लिए एक प्रतिनिधि लेता है। आप इसे इस तरह का उपयोग कर सकते हैं:

tmpCLientList.RemoveAll(cli => cli.Name != txtboxClientName.Text); 
+0

+1 साझा करने के लिए धन्यवाद एक को ध्यान रखना चाहिए कि यह केवल सी # 3.0 और ऊपर के लिए काम करता है। ओपी ने संस्करण 2, 3, और 4 के साथ प्रश्न टैग किया :-) –

+1

@ जैकोब: यदि ओपी सी # 3 या नए का उपयोग नहीं कर रहा है तो वे पुरानी-स्कूल प्रतिनिधि वाक्यविन्यास के साथ 'RemoveAll' को कॉल कर सकते हैं:' tmpCLientList.RemoveAll (प्रतिनिधि (क्लाइंट क्ली) {वापसी cli.Name! = txtboxClientName.Text;}); ' – LukeH

+0

ओह सही - सोचा कि RemoveAll एक विस्तार विधि थी। इसके बारे में क्षमा करें :-) –

1

आप आइटम आप हटा सकते हैं और अपने "txtboxClientName" सूची से आइटम हटाने के लिए नई सूची पुनरावृति करना चाहते हैं के साथ एक और सूची बना सकते हैं।

+0

ठीक है, मैं कॉपी सूची पर कंटेनर() और निकालें() विधियों का उपयोग कर सकता हूं, जबकि मूल पर पुनरावृत्ति करता हूं। धन्यवाद। – qlf00n

1

दरअसल, फोरच दिए गए आइटम-संग्रह के माध्यम से गणना करने के लिए अंकुशकों का उपयोग करता है। आगे बढ़कर System.Collections.Generic.List<T>IEnumarable-Interface से provide a Class लागू करता है, जो जानता है कि सूची के आइटमों के माध्यम से पुनरावृत्ति कैसे करें, यानी Enumerator। अब अगर आप उस सूची के माध्यम से फ़ोरैच का उपयोग करके पुन: प्रयास करते हैं तो एन्युमरेटर वर्तमान स्थिति का ट्रैक रखता है, अगली स्थिति और कुछ अन्य सामान तक कैसे पहुंचे। आंतरिक तर्क एक चर एन में वस्तुओं की संख्या को संग्रहीत करने जैसा कुछ हो सकता है और फिर 0 से n-1 तक सभी ऑब्जेक्ट्स तक पहुंच सकता है। जैसा कि आप नोटिस कर सकते हैं कि पुनरावृत्ति चरणों के बीच कोई वस्तु हटा दी गई है, तो हम NullReferenceException में समाप्त हो जाएंगे जब गणनाकर्ता सूची की अंतिम वस्तु को वितरित करने का प्रयास करता है। इसलिए किसी भी पुनरावृत्ति विफलताओं को रोकने के लिए, गणना के दौरान सूची को संशोधित करने की अनुमति नहीं है।

आशा है कि मैं इसे कम से कम थोड़ा सा बता सकता हूं। :-)

+0

बहुत सटीक जानकारी के लिए धन्यवाद, जीटीके यह आंतरिक रूप से कैसे काम करता है – qlf00n

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