इस पर पुनरावृत्ति करते हुए जेनेरिक सूची से तत्वों को कैसे हटाया जाए?


451

मैं उन तत्वों की सूची के साथ काम करने के लिए एक बेहतर पैटर्न की तलाश में हूं, जिन्हें प्रत्येक को संसाधित करने की आवश्यकता होती है और फिर परिणाम के आधार पर सूची से हटा दिया जाता है।

आप .Remove(element)एक के अंदर उपयोग नहीं कर सकते foreach (var element in X)(क्योंकि यह Collection was modified; enumeration operation may not execute.अपवाद के रूप में परिणाम है) ... आप भी उपयोग नहीं कर सकते हैं for (int i = 0; i < elements.Count(); i++)और .RemoveAt(i)क्योंकि यह आपके सापेक्ष संग्रह में वर्तमान स्थिति को बाधित करता है i

क्या ऐसा करने का एक सुंदर तरीका है?

जवाबों:


734

अपनी सूची को एक लूप के साथ उल्टे क्रमबद्ध करें:

for (int i = safePendingList.Count - 1; i >= 0; i--)
{
    // some code
    // safePendingList.RemoveAt(i);
}

उदाहरण:

var list = new List<int>(Enumerable.Range(1, 10));
for (int i = list.Count - 1; i >= 0; i--)
{
    if (list[i] > 5)
        list.RemoveAt(i);
}
list.ForEach(i => Console.WriteLine(i));

वैकल्पिक रूप से, आप के खिलाफ परीक्षण करने के लिए एक विधेय के साथ RemoveAll विधि का उपयोग कर सकते हैं :

safePendingList.RemoveAll(item => item.Value == someValue);

यहाँ एक सरल उदाहरण प्रदर्शित करना है:

var list = new List<int>(Enumerable.Range(1, 10));
Console.WriteLine("Before:");
list.ForEach(i => Console.WriteLine(i));
list.RemoveAll(i => i > 5);
Console.WriteLine("After:");
list.ForEach(i => Console.WriteLine(i));

19
जावा से आने वालों के लिए, C # की सूची ArrayList की तरह है जिसमें प्रविष्टि / निष्कासन O (n) है और एक सूचकांक के माध्यम से पुनर्प्राप्ति O (1) है। यह वह जगह है नहीं एक पारंपरिक लिंक्ड सूची। यह थोड़ा दुर्भाग्यपूर्ण लगता है C # इस डेटा संरचना का वर्णन करने के लिए "सूची" शब्द का उपयोग करता है क्योंकि यह क्लासिक लिंक्ड सूची को ध्यान में रखता है।
जारोद स्मिथ

79
'लिस्ट' नाम की कोई भी चीज 'लिंक्डलिस्ट' नहीं कहती है। जावा के अलावा अन्य भाषाओं से आने वाले लोग भ्रमित हो सकते हैं जब यह एक लिंक की गई सूची होगी।
GolezTrol

5
मैं vb.net खोज के माध्यम से यहाँ समाप्त हुआ, अगर कोई भी निकाले जाने के लिए vb.net समकक्ष सिंटैक्स चाहता है:list.RemoveAll(Function(item) item.Value = somevalue)
pseudocoder

1
यह जावा में न्यूनतम संशोधन के साथ भी काम करता है: के .size()बजाय .Countऔर के .remove(i)बजाय .removeAt(i)। चालाक - धन्यवाद!
शरद ऋतु लियोनार्ड

2
मैंने प्रदर्शन के लिए थोड़ा परीक्षण किया और यह पता चला कि RemoveAll()बैकवर्ड forलूप के रूप में तीन गुना अधिक समय लगता है । इसलिए मैं निश्चित रूप से लूप के साथ चिपका रहा हूं, कम से कम उन वर्गों में जहां यह मायने रखता है।
क्रुशा के। रुल

84

एक सरल और सीधा समाधान:

अपने संग्रह पर पीछे की ओर चलने वाले और RemoveAt(i)तत्वों को हटाने के लिए एक मानक फॉर-लूप का उपयोग करें ।


2
इस बात से अवगत रहें कि यदि आपकी सूची में कई आइटम हैं, तो आइटम को एक बार में निकालना कुशल नहीं है । इसमें O (n ^ 2) होने की क्षमता है। दो बिलियन आइटम्स के साथ एक लिस्ट की कल्पना करें जहां ऐसा होता है कि सभी बिलियन आइटम पहले ही डिलीट हो जाते हैं। प्रत्येक निष्कासन सभी बाद की वस्तुओं को कॉपी करने के लिए मजबूर करता है, इसलिए आप प्रत्येक बार एक बिलियन आइटम को एक अरब गुना कॉपी करते हैं। यह रिवर्स पुनरावृत्ति के कारण नहीं है, यह एक बार हटाने के कारण है। RemoveAll यह सुनिश्चित करता है कि प्रत्येक आइटम को एक बार कॉपी किया जाए ताकि वह रैखिक हो। एक बार में हटाने पर एक अरब गुना धीमा हो सकता है। O (n) बनाम O (n ^ 2)।
ब्रूस डॉसन

71

जब आप एक संग्रह से तत्वों को हटाना चाहते हैं तो उल्टा चलना पहली बात होनी चाहिए।

सौभाग्य से, लूप के लिए लिखने की तुलना में अधिक सुरुचिपूर्ण समाधान है जिसमें अनावश्यक टाइपिंग शामिल है और त्रुटि प्रवण हो सकता है।

ICollection<int> test = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});

foreach (int myInt in test.Reverse<int>())
{
    if (myInt % 2 == 0)
    {
        test.Remove(myInt);
    }
}

7
इसने मेरे लिए पूरी तरह से काम किया। मेरे कोड में सरल, और सुरुचिपूर्ण और आवश्यक न्यूनतम परिवर्तन।
स्टीफन मैकडॉगल

1
क्या यह सिर्फ फ्लिपिन जीनियस है? और मैं @StephenMacDougall से सहमत हूं, मुझे लूप के लिए उन C ++ 'y का उपयोग करने की आवश्यकता नहीं है और केवल LINQ के साथ ही प्राप्त करें।
पिओटर कुला

5
मुझे साधारण फॉर्च्यूशन (टेस्ट में myInt; intList) ()) {if (myInt% 2 == 0) {test.Remove (myInt) पर कोई लाभ नहीं दिखता है; }} आपको अभी भी रिवर्स के लिए एक प्रति आवंटित करना है और यह हुह का परिचय देता है? पल - उल्टा क्यों है।
जाह्ववी

11
@jedesah जी हाँ, Reverse<T>()एक पुनरावृत्त बनाता है , जो सूची के पीछे से होकर जाता है, लेकिन यह अतिरिक्त बफर को उसी आकार के साथ आवंटित करता है, जो इसके लिए सूची में ही है ( Referenceource.microsoft.com/#System.Core/System/Linq/… )। Reverse<T>केवल रिवर्स ऑर्डर में मूल सूची के माध्यम से नहीं जाता है (w / o अतिरिक्त मेमोरी आवंटित करता है)। इसलिए दोनों ToList()और Reverse()एक ही स्मृति की खपत (दोनों प्रतिलिपि बनाने) है, लेकिन ToList()डेटा के लिए कुछ भी नहीं है। के साथ Reverse<int>(), मुझे आश्चर्य होगा कि सूची किस कारण से उलट है।
जावेद

1
@ सहज मैं आपकी बात देखता हूँ। यह काफी निराशाजनक है कि Reverse<T>()एक नया बफर बनाने का कार्यान्वयन , मुझे पूरा यकीन नहीं है कि मैं समझता हूं कि यह आवश्यक क्यों है। यह मुझे लगता है कि अंतर्निहित संरचना के आधार पर Enumerable, कम से कम कुछ मामलों में रैखिक स्मृति को आवंटित किए बिना रिवर्स चलना प्राप्त करना संभव होना चाहिए।
जेद्दाह

68
 foreach (var item in list.ToList()) {
     list.Remove(item);
 }

यदि आप अपनी सूची में ".ToList ()" (या एक LINQ क्वेरी के परिणाम ) जोड़ते हैं , तो आप "आइटम" को सीधे "सूची" से हटा सकते हैं बिना खूंखार " संग्रह संशोधित किया गया था; गणना संचालन निष्पादित नहीं हो सकता है ।" त्रुटि। संकलक "सूची" की एक प्रतिलिपि बनाता है, ताकि आप सरणी पर सुरक्षित रूप से हटा सकें।

हालांकि यह पैटर्न सुपर कुशल नहीं है, लेकिन यह एक प्राकृतिक अनुभव है और लगभग किसी भी स्थिति के लिए पर्याप्त लचीला है । जैसे कि जब आप प्रत्येक "आइटम" को किसी DB में सहेजना चाहते हैं और सूची से तभी हटाते हैं जब DB सहेजता है।


6
यदि दक्षता महत्वपूर्ण नहीं है तो यह सबसे अच्छा समाधान है।
इवान

2
यह तेज़ और अधिक पठनीय है: सूची .emoveAll (i => true);
सैंटियागो अरीज़ती

1
@ ग्रेट लिटिल, क्या मैं आपको सही ढंग से समझ पाया हूं - जब आप टॉलिस्ट जोड़ते हैं () कंपाइलर कॉपी किए गए संग्रह से गुजरता है लेकिन मूल से हटा देता है?
Pyrejkee

यदि आपकी सूची में डुप्लिकेट आइटम हैं और आप केवल सूची में बाद में होने वाली वस्तु को निकालना चाहते हैं तो क्या यह गलत आइटम को नहीं हटाएगा?
टिम एमबी

क्या यह वस्तुओं की सूची के लिए भी काम करता है?
टॉम एल सफादी

23

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

var newSequence = (from el in list
                   where el.Something || el.AnotherThing < 0
                   select el);

मैं इसे माइकल डिलन द्वारा नीचे दी गई टिप्पणी के जवाब में एक टिप्पणी के रूप में पोस्ट करना चाहता था, लेकिन यह मेरे जवाब में वैसे भी बहुत लंबा और शायद उपयोगी है:

व्यक्तिगत रूप से, मैं कभी भी एक-एक करके आइटम नहीं निकालूंगा, यदि आपको हटाने की आवश्यकता है, तो कॉल करें RemoveAllजो एक विधेय लेता है और केवल एक बार आंतरिक सरणी को पुनर्व्यवस्थित Removeकरता है , जबकि Array.Copyआपके द्वारा हटाए गए प्रत्येक तत्व के लिए एक ऑपरेशन करता है । RemoveAllबहुत अधिक कुशल है।

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

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


1
या तो यह, या एक अवांछित सूची में एक सूचक को दूसरी सूची में जोड़ें, फिर आपके लूप के समाप्त होने के बाद, निष्कासन सूची को पुनरावृत्त करें और तत्वों को निकालने के लिए इसका उपयोग करें।
माइकल डिलन

22

सामान्य सूची पर ToArray () का उपयोग करने से आप अपनी जेनेरिक सूची में एक निकालें (आइटम) कर सकते हैं:

        List<String> strings = new List<string>() { "a", "b", "c", "d" };
        foreach (string s in strings.ToArray())
        {
            if (s == "b")
                strings.Remove(s);
        }

2
यह गलत नहीं है, लेकिन मुझे यह बताना होगा कि यह पूरी सूची को एक सरणी में कॉपी करने की कीमत पर आपके द्वारा हटाए गए आइटमों की दूसरी "संग्रहण" सूची बनाने की आवश्यकता को दरकिनार कर देता है। हाथ से चुने गए तत्वों की दूसरी सूची में संभवतः कम आइटम होंगे।
अहमद ने

20

.ToList () का उपयोग करके आपकी सूची की एक प्रति बन जाएगी, जैसा कि इस प्रश्न में बताया गया है: ToList () - क्या यह एक नई सूची बनाता है?

ToList () का उपयोग करके, आप अपनी मूल सूची से हटा सकते हैं, क्योंकि आप वास्तव में एक कॉपी पर पुनरावृत्ति कर रहे हैं।

foreach (var item in listTracked.ToList()) {    

        if (DetermineIfRequiresRemoval(item)) {
            listTracked.Remove(item)
        }

     }

1
लेकिन प्रदर्शन के दृष्टिकोण से आप अपनी सूची की प्रतिलिपि बना रहे हैं, जिसमें कुछ समय लग सकता है। इसे करने का अच्छा और आसान तरीका है, लेकिन इतने अच्छे प्रदर्शन के साथ नहीं
फ्लोरियन के

12

यदि फ़ंक्शन जो यह निर्धारित करता है कि कौन से आइटम को हटाना कोई दुष्प्रभाव नहीं है और आइटम को म्यूट नहीं करता है (यह एक शुद्ध कार्य है), एक सरल और कुशल (रैखिक समय) समाधान है:

list.RemoveAll(condition);

यदि साइड इफेक्ट होते हैं, तो मैं कुछ का उपयोग करूंगा:

var toRemove = new HashSet<T>();
foreach(var item in items)
{
     ...
     if(condition)
          toRemove.Add(item);
}
items.RemoveAll(toRemove.Contains);

यह अभी भी रैखिक समय है, यह मानते हुए कि हैश अच्छा है। लेकिन हैशसेट के कारण इसका बढ़ा हुआ मेमोरी उपयोग है।

अंत में यदि आपकी सूची केवल एक के IList<T>बजाय एक है तो List<T>मैं अपने जवाब का सुझाव देता हूं कि मैं इस विशेष फ़ॉरचेट इट्रेटर को कैसे कर सकता हूं? । इसमें IList<T>कई अन्य उत्तरों के द्विघात रनटाइम के साथ तुलनात्मक रूप से रैखिक कार्यान्वयन दिया जाएगा ।


11

जैसा कि किसी भी शर्त को हटा दिया जाता है जिसे आप उपयोग कर सकते हैं

list.RemoveAll(item => item.Value == someValue);

यह सबसे अच्छा समाधान है अगर प्रसंस्करण आइटम को म्यूट नहीं करता है और इसका कोई साइड इफेक्ट नहीं है।
कोडइन्चोस


8

आप फॉर्च्यूनर का उपयोग नहीं कर सकते हैं, लेकिन जब आप किसी आइटम को निकालते हैं, तो आप आगे की ओर बढ़ सकते हैं और अपने लूप इंडेक्स वैरिएबल को प्रबंधित कर सकते हैं, जैसे:

for (int i = 0; i < elements.Count; i++)
{
    if (<condition>)
    {
        // Decrement the loop counter to iterate this index again, since later elements will get moved down during the remove operation.
        elements.RemoveAt(i--);
    }
}

ध्यान दें कि सामान्य तौर पर ये सभी तकनीकें संग्रह के व्यवहार पर निर्भर करती हैं। यहां दिखाई गई तकनीक मानक सूची (टी) के साथ काम करेगी। (यह संभव है अपने स्वयं के संग्रह वर्ग लिखने के लिए और इटरेटर कि करता है एक foreach पाश के दौरान आइटम हटाने अनुमति देते हैं।)


6

किसी सूची का उपयोग करना Removeया RemoveAtउस सूची पर पुनरावृत्ति करना जानबूझकर कठिन बना दिया गया है, क्योंकि यह लगभग हमेशा गलत काम है । आप इसे कुछ चालाक चाल के साथ काम करने में सक्षम कर सकते हैं, लेकिन यह बहुत धीमा होगा। हर बार जब आप कॉल Removeकरते हैं तो आपको जिस लिस्ट को हटाना चाहते हैं उसे ढूंढने के लिए पूरी लिस्ट को स्कैन करना पड़ता है। हर बार जब आप कॉल RemoveAtकरते हैं तो बाद के तत्वों को 1 स्थिति में बाईं ओर ले जाना पड़ता है। जैसे, किसी भी समाधान का उपयोग करना Removeया RemoveAt, द्विघात समय की आवश्यकता होगी, O (n using) । ।

RemoveAllयदि आप कर सकते हैं का उपयोग करें । अन्यथा, निम्न पैटर्न रैखिक समय, O (n) में सूची को जगह में फ़िल्टर करेगा ।

// Create a list to be filtered
IList<int> elements = new List<int>(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
// Filter the list
int kept = 0;
for (int i = 0; i < elements.Count; i++) {
    // Test whether this is an element that we want to keep.
    if (elements[i] % 3 > 0) {
        // Add it to the list of kept elements.
        elements[kept] = elements[i];
        kept++;
    }
}
// Unfortunately IList has no Resize method. So instead we
// remove the last element of the list until: elements.Count == kept.
while (kept < elements.Count) elements.RemoveAt(elements.Count-1);

3

मैं इच्छा "पैटर्न" कुछ इस तरह था:

foreach( thing in thingpile )
{
    if( /* condition#1 */ )
    {
        foreach.markfordeleting( thing );
    }
    elseif( /* condition#2 */ )
    {
        foreach.markforkeeping( thing );
    }
} 
foreachcompleted
{
    // then the programmer's choices would be:

    // delete everything that was marked for deleting
    foreach.deletenow(thingpile); 

    // ...or... keep only things that were marked for keeping
    foreach.keepnow(thingpile);

    // ...or even... make a new list of the unmarked items
    others = foreach.unmarked(thingpile);   
}

यह प्रोग्रामर के मस्तिष्क में जाने वाली प्रक्रिया के साथ कोड को संरेखित करेगा।


1
काफी आसान। बस एक बूलियन फ़्लैग ऐरे बनाएं (3-स्टेट प्रकार का उपयोग करें, उदाहरण के लिए Nullable<bool>, यदि आप बिना अनुमति देना चाहते हैं), तो आइटम हटाने / रखने के लिए फ़ॉरचेक के बाद इसका उपयोग करें।
दान बेचर

3

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

        int i = 0;
        while (i < list.Count())
        {
            if (list[i].predicate == true)
            {
                list.RemoveAt(i);
                continue;
            }
            i++;
        }

मैंने इसे एक उत्थान दिया क्योंकि कभी-कभी यह सूची में क्रम से स्थानांतरित करने के लिए अधिक कुशल हो सकता है (रिवर्स ऑर्डर नहीं)। शायद पहले आइटम को हटाने के लिए आप रोक सकते हैं क्योंकि सूची का आदेश नहीं दिया गया है। (एक 'विराम' की कल्पना कीजिए जहाँ i ++ इस उदाहरण में है।
FrankKrumnow

3

मैं एक LINQ क्वेरी से सूची को फिर से असाइन करूँगा जो उन तत्वों को फ़िल्टर करती है जिन्हें आप नहीं रखना चाहते हैं।

list = list.Where(item => ...).ToList();

जब तक सूची बहुत बड़ी नहीं है, ऐसा करने में कोई महत्वपूर्ण प्रदर्शन समस्या नहीं होनी चाहिए।


3

किसी सूची से आइटम्स को निकालने का सबसे अच्छा तरीका यह है कि इसका उपयोग करना है RemoveAll() । लेकिन लोगों द्वारा लिखित मुख्य चिंता यह है कि उन्हें लूप के अंदर कुछ जटिल चीजें करनी हैं और / या जटिल तुलनात्मक मामले हैं।

समाधान अभी भी उपयोग करना है RemoveAll()लेकिन इस अंकन का उपयोग करें:

var list = new List<int>(Enumerable.Range(1, 10));
list.RemoveAll(item => 
{
    // Do some complex operations here
    // Or even some operations on the items
    SomeFunction(item);
    // In the end return true if the item is to be removed. False otherwise
    return item > 5;
});

2
foreach(var item in list.ToList())

{

if(item.Delete) list.Remove(item);

}

बस पहले एक से एक पूरी तरह से नई सूची बनाएं। मैं कहता हूं कि "राइट" के बजाय "राइट" के रूप में एक पूरी तरह से नई सूची बनाने के लिए संभवतः पिछले पद्धति पर एक प्रदर्शन प्रीमियम आता है (मैंने किसी भी बेंचमार्किंग से परेशान नहीं किया है।) मैं आमतौर पर इस पैटर्न को पसंद करता हूं, यह ओवरराइड करने में भी उपयोगी हो सकता है। Linq-To-Entities सीमाएँ।

for(i = list.Count()-1;i>=0;i--)

{

item=list[i];

if (item.Delete) list.Remove(item);

}

इस तरह सूची के माध्यम से पीछे की ओर एक पुराने पुराने लूप के साथ चक्र होता है। यदि संग्रह का आकार बदलता है, तो इसे आगे करना समस्याग्रस्त हो सकता है, लेकिन पीछे की तरफ हमेशा सुरक्षित होना चाहिए।


1

उस सूची की प्रतिलिपि बनाएँ जिसे आप पुनरावृत्त कर रहे हैं। फिर कॉपी से निकालें और मूल को इंटर करें। पीछे की ओर जाना भ्रामक है और जब समानांतर में लूपिंग अच्छी तरह से काम नहीं करता है।

var ids = new List<int> { 1, 2, 3, 4 };
var iterableIds = ids.ToList();

Parallel.ForEach(iterableIds, id =>
{
    ids.Remove(id);
});

1

मैं ऐसा करूंगा

using System.IO;
using System;
using System.Collections.Generic;

class Author
    {
        public string Firstname;
        public string Lastname;
        public int no;
    }

class Program
{
    private static bool isEven(int i) 
    { 
        return ((i % 2) == 0); 
    } 

    static void Main()
    {    
        var authorsList = new List<Author>()
        {
            new Author{ Firstname = "Bob", Lastname = "Smith", no = 2 },
            new Author{ Firstname = "Fred", Lastname = "Jones", no = 3 },
            new Author{ Firstname = "Brian", Lastname = "Brains", no = 4 },
            new Author{ Firstname = "Billy", Lastname = "TheKid", no = 1 }
        };

        authorsList.RemoveAll(item => isEven(item.no));

        foreach(var auth in authorsList)
        {
            Console.WriteLine(auth.Firstname + " " + auth.Lastname);
        }
    }
}

आउटपुट

Fred Jones
Billy TheKid

0

मैं खुद को एक ऐसी ही स्थिति में पाया जहां मैं हर n निकालनी पड़ी वें किसी दिए गए में तत्व List<T>

for (int i = 0, j = 0, n = 3; i < list.Count; i++)
{
    if ((j + 1) % n == 0) //Check current iteration is at the nth interval
    {
        list.RemoveAt(i);
        j++; //This extra addition is necessary. Without it j will wrap
             //down to zero, which will throw off our index.
    }
    j++; //This will always advance the j counter
}

0

सूची से एक आइटम को हटाने की लागत एक हटाए जाने के बाद की वस्तुओं की संख्या के लिए आनुपातिक है। उस स्थिति में जहां पहली छमाही में वस्तुएं हटाने की पात्रता होती है, कोई भी दृष्टिकोण जो व्यक्तिगत रूप से वस्तुओं को हटाने पर आधारित होता है, समाप्त हो जाएगा एन * एन / 4 आइटम-कॉपी संचालन के बारे में, जो सूची बड़ी होने पर बहुत महंगा हो सकता है ।

एक तेज़ दृष्टिकोण सूची के माध्यम से स्कैन करना है ताकि पहले आइटम को निकाला जा सके (यदि कोई हो), और फिर उस बिंदु से आगे प्रत्येक आइटम को कॉपी करें जिसे उस स्थान पर रखा जाना चाहिए जहां यह है। एक बार यह पूरा हो जाने के बाद, यदि आर आइटम को बरकरार रखा जाना चाहिए, तो सूची में पहला आर आइटम उन आर आइटम होंगे, और हटाने की आवश्यकता वाले सभी आइटम अंत में होंगे। यदि उन वस्तुओं को उल्टे क्रम में हटा दिया जाता है, तो सिस्टम उनमें से किसी को भी कॉपी करने के लिए समाप्त नहीं होगा, इसलिए यदि सूची में N आइटम थे जिनमें से R आइटम, जिसमें पहले F, सहित सभी को बरकरार रखा गया था, यह आवश्यक होगा RF आइटम की प्रतिलिपि बनाएँ, और सूची को एक आइटम NR बार से सिकोड़ें। सभी रैखिक समय।


0

मेरा दृष्टिकोण यह है कि मैं सबसे पहले सूचकांकों की सूची बनाता हूं, जिन्हें हटा दिया जाना चाहिए। बाद में मैं सूचकांक पर लूप करता हूं और प्रारंभिक सूची से आइटम हटा देता हूं। यह इस तरह दिखता है:

var messageList = ...;
// Restrict your list to certain criteria
var customMessageList = messageList.FindAll(m => m.UserId == someId);

if (customMessageList != null && customMessageList.Count > 0)
{
    // Create list with positions in origin list
    List<int> positionList = new List<int>();
    foreach (var message in customMessageList)
    {
        var position = messageList.FindIndex(m => m.MessageId == message.MessageId);
        if (position != -1)
            positionList.Add(position);
    }
    // To be able to remove the items in the origin list, we do it backwards
    // so that the order of indices stays the same
    positionList = positionList.OrderByDescending(p => p).ToList();
    foreach (var position in positionList)
    {
        messageList.RemoveAt(position);
    }
}

0

C # में एक आसान तरीका यह है कि आप जिसे हटाना चाहते हैं उसे चिह्नित करें और फिर से पुनरावृति करने के लिए एक नई सूची बनाएं ...

foreach(var item in list.ToList()){if(item.Delete) list.Remove(item);}  

या यहां तक ​​कि सरल उपयोग linq ....

list.RemoveAll(p=>p.Delete);

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


0

एक संपत्ति के साथ हटाए जाने वाले तत्वों को ट्रेस करें, और प्रक्रिया के बाद उन सभी को हटा दें।

using System.Linq;

List<MyProperty> _Group = new List<MyProperty>();
// ... add elements

bool cond = true;
foreach (MyProperty currObj in _Group)
{
    if (cond) 
    {
        // SET - element can be deleted
        currObj.REMOVE_ME = true;
    }
}
// RESET
_Group.RemoveAll(r => r.REMOVE_ME);

0

बस इस मामले में मेरे 2 सेंट जोड़ना चाहते थे इससे किसी को भी मदद मिलती है, मुझे एक समान समस्या थी लेकिन एक सरणी सूची से कई तत्वों को हटाने की आवश्यकता थी, जबकि इसे पुनरावृत्त किया जा रहा था। उच्चतम उत्तोलित उत्तर ने मुझे सबसे अधिक भाग के लिए तब तक किया जब तक कि मैं त्रुटियों में भाग नहीं गया और महसूस किया कि सूचकांक कुछ उदाहरणों में सरणी सूची के आकार से अधिक था क्योंकि कई तत्वों को हटाया जा रहा था लेकिन लूप का सूचकांक नहीं रखा गया था उस पर नज़र रखें। मैंने इसे एक साधारण जाँच के साथ तय किया:

ArrayList place_holder = new ArrayList();
place_holder.Add("1");
place_holder.Add("2");
place_holder.Add("3");
place_holder.Add("4");

for(int i = place_holder.Count-1; i>= 0; i--){
    if(i>= place_holder.Count){
        i = place_holder.Count-1; 
    }

// some method that removes multiple elements here
}

-4
myList.RemoveAt(i--);

simples;

1
simples;यहाँ क्या करता है?
डेनी

6
इसका एक प्रतिनिधि .. यह मेरे जवाब को हर बार जब यह चलता है
SW

SW ROFL! होगा अपनी टिप्पणी प्यार करता हूँ।
इरिक ब्राउन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.