2009-07-14 7 views
8

में फ़ोरैच लूप का उपयोग करते समय संग्रह संशोधित करना मूल रूप से, मैं फ़ोरैच लूप के अंदर एक सूची से किसी आइटम को हटाना चाहता हूं। मुझे पता है कि लूप का उपयोग करते समय यह संभव है, लेकिन अन्य उद्देश्यों के लिए, मैं जानना चाहता हूं कि यह फ़ोरैच लूप का उपयोग करके प्राप्त किया जा सकता है या नहीं।सी #

a = [1, 2, 3, 4, 5, 6, 7, 8, 9] 

for i in a: 
    print i 

    if i == 1: 
     a.pop(1) 

यह निम्न आउटपुट

>>>1 
3 
4 
5 
6 
7 
8 
9 

लेकिन जब सी # में इसी तरह कुछ कर रही है, मैं एक InvalidOperationException मिल देता है, मैं सोच रहा था:

अजगर में हम निम्न तरीके से प्राप्त कर सकते हैं अगर इसके आसपास होने का कोई तरीका था, बस लूप के लिए बस उपयोग किए बिना।

सी # में कोड है कि मैं जब अपवाद उत्पन्न हुआ था इस्तेमाल किया:

static void Main(string[] args) 
    { 
    List<string> MyList = new List<string>(new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9"}); 

    foreach (string Item in MyList) 
    { 
    if (MyList.IndexOf(Item) == 0) 
     { 
     MyList.RemoveAt(1); 
     } 

    Console.WriteLine(Item); 
    } 
    } 

अग्रिम

उत्तर

25

धन्यवाद आप ऐसा नहीं कर सकते। IEnumerator<T> के लिये दस्तावेज से:

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

विकल्प हैं:

  • ऊपर मदों की एक नई सूची को हटाने के लिए, सभी बाद में
  • पाश "के लिए" का प्रयोग करें एक सामान्य बिल्ड फिर उन्हें हटा दें और सुनिश्चित करें कि आप नहीं जा रहा बारे में सावधान कर रहे हैं एक ही तत्व पर दो बार या किसी भी गायब हो रहा है। (आप जो बोलते हैं उसे आप ऐसा करना नहीं चाहते हैं, लेकिन सिर्फ काम नहीं करेगा आप क्या करने की कोशिश कर रहे हैं क्या।)
  • केवल तत्वों आप

बनाए रखने के लिए चाहते हैं एक नया संग्रह बनाएँ

var newList = oldList.Where(x => ShouldBeRetained(x)).ToList(); 

ToList() करने के लिए कॉल केवल आवश्यक है (। ShouldBeRetained कहाँ जो कुछ भी तर्क आप निश्चित रूप से चाहते हैं, है) यदि आप वास्तव में चाहते हैं: इन विकल्पों के अंतिम LINQ की तरह समाधान है, जहां आप आमतौर पर लिखने होता है यह एक सूची में है। इससे अधिक घोषणात्मक कोड होता है जो अक्सर पढ़ने में आसान होता है। मैं आसानी से अनुमान लगा सकता हूं कि आपका मूल पाश क्या करना है (यह इस समय बहुत अजीब लगता है) जबकि यदि आप आइटम के संदर्भ में तर्क को पूरी तरह व्यक्त कर सकते हैं, तो यह बहुत स्पष्ट हो सकता है।

+0

मैं मुख्य रूप से सोच रहा था कि अगर मैं foreach उदाहरण के साथ कहीं कुछ याद किया था, लेकिन अगर यह प्राप्त करने योग्य नहीं है, कम से कम अब इसकी पुष्टि हुई है! जवाब के लिए धन्यवाद – ThePower

1

आप निश्चित रूप से किसी भी तरह से फ़ोरैच लूप का उपयोग करते समय संग्रह को किसी भी रूप में नहीं बदल सकते हैं।

आप लूप के लिए उपयोग कर सकते हैं और अपने लिए इंडेक्स प्रबंधित कर सकते हैं या संग्रह की एक प्रति बना सकते हैं और जैसे ही आप मूल लूप कर रहे हैं, मूल में आइटम के बराबर प्रतिलिपि से आइटम हटा दें।

दोनों मामलों में यह स्पष्ट या सुविधाजनक नहीं है :)।

6

आप सभी की जरूरत सभी आइटम है कि एक शर्त को पूरा दूर करने के लिए आप List<T>.RemoveAll विधि का उपयोग कर सकते है:

List<string> MyList = new List<string>(new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" }); 
MyList.RemoveAll(item => item == "1"); 

ध्यान दें कि यह प्रारंभिक सूची संशोधित करता है।