2016-02-28 9 views
6

मेरे पास 2 सूची हैं जिनके नाम सूची हैं और सूची बी।किसी अन्य सूची से सूची में तारों को कैसे निकालें?

मैं listB में तार जो लिस्टा में हैं निकालना चाहते हैं, लेकिन मैं इस तरह से ऐसा करना चाहते हैं:

अगर लिस्टा शामिल हैं: "बार", "बार", "बार", "foo" और listB शामिल हैं: "बार"

यह केवल 1 बार दूर करता है और परिणाम होगा: "बार", "बार", "foo"

कोड मैंने लिखा सब "बार" निकालता है:

List<string> result = listA.Except(listB).ToList(); 
+0

मूल सूची के आदेश बात को भी बचाए रखा है? – hatchet

उत्तर

5

आप एक के बाद यह एक दूर करने की कोशिश कर सकते हैं:

foreach (var word in listB) 
    listA.Remove(word); 

निकालें विधि एक बार में केवल एक ही तत्व निकाल देंगे और अपवाद फेंक नहीं है (लेकिन झूठी लौटने) जब आइटम नहीं मिला है: https://msdn.microsoft.com/en-us/library/cd666k3e(v=vs.110).aspx

+0

स्थिति – Steve

+1

प्राप्त करने के लिए आप सीधे इंडेक्स का उपयोग कर कॉल शामिल कर सकते हैं यह अक्षम है, लेकिन आप इसे कम से कम सीधे 'listA.Remove (word)' का उपयोग कर सकते हैं। 'शामिल' की कोई ज़रूरत नहीं है। –

+0

@IvanStoev सही, बस इसे – Ian

3
var listA = new List<string>() { "bar", "bar", "bar", "foo" }; 
var listB = new List<string>() { "bar" }; 

foreach (var word in listB){ 
    listA.Remove(word); 
} 
+0

अपडेट करें यह मूल रूप से @Ian उत्तर की एक प्रति आपके –

+0

से 10+ मिनट पहले पोस्ट किया गया है, यह सच है, मैंने अपना जवाब – csa

1

यह एक तेज़ तरीका है लेकिन यह पहली सूची के तत्वों के क्रम को बदलने की संभावना है। कदम:

  • एक Dictionary<string, int> (यह listAMap कॉल), जहां कुंजी सूची के तत्व है और मूल्य बार है कि मूल्य लिस्टा में हुआ है की कुल संख्या है करने के लिए मानचित्र लिस्टा;
  • listB के माध्यम से Iterate और सूची बी के प्रत्येक तत्व के लिए, यदि वह तत्व listAMap में है, तो इसकी गणना कम करें;
  • सी # शब्दकोशों के Keys property का उपयोग करके listMapA की चाबियाँ प्राप्त करें, और सभी चाबियों के माध्यम से पुनरावृत्त करें। प्रत्येक कुंजी के लिए जो सकारात्मक मान है, उस कुंजी को दूसरी सूची में जोड़ दें, इसकी कुल गणना समय। तो यदि कोई प्रविष्टि "bar" -> 2 है, तो नई सूची में दो बार "बार" जोड़ें।

एल्गोरिथ्म के कुल रन टाइम ओ (m + n), वह जगह है जहाँ एम और एन दोनों मूल सूचियों में तत्वों की संख्या है। यह यहां वर्णित अन्य दृष्टिकोणों की तुलना में बेहतर समय है, जिसमें ओ (एम * एन) चलने का समय है। जाहिर है यह एल्गोरिदम अधिक जगह का उपयोग करता है। उपरोक्त एल्गोरिथ्म के लिए


सहायक कोड:

//Step-1: Create the dictionary... 
var listAMap = new Dictionary<string, int>(); 
foreach (var listAElement in listA) 
{ 
    listAMap.ContainsKey(listAElement) ? listAMap[listAElement]++ : listAMap.Add(listAElement, 1); 
} 

// Step-2: Remove the listB elements from dictionary... 
foreach (var listBElement in listB) 
{ 
    if (listAMap.Contains(listBElement)) listAMap[listBElement]--; 
} 

//Step-3: Create the new list from pruned dictionary... 
var prunedListA = new List<string>(); 
foreach (var key in listAMap.Keys) 
{ 
    if (listAMap[key] <= 0) continue; 
    for (var count = 0; count < listAMap[key]; count++) 
    { 
     prunedListA.Add(key); 
    } 
} 

//prunedListA contains the desired elements now. 
+0

ऊपर उठाया था, मैं कुछ समान सोच रहा था, लेकिन सूची बी गिन रहा था और फिर हटा रहा था सूची ए टाह मैच से आइटम (और मिलान करने वाली गिनती में कमी)। वैसे भी, दक्षता के बारे में सोचने के लिए +1। –

+0

@IvanStoev: हम सूची में आइटम मिलान नहीं कर रहे हैं।हम एक शब्दकोश में ओ (1) लुकअप कर रहे हैं। गंभीरता से, समाधान बहुत सरल है (नहीं कि आप उत्तर पर +2 दे सकते हैं)। मुझे कोड भी जोड़ना चाहिए था। जब मैं लैपटॉप से ​​SO तक पहुंचता हूं तो करूँगा। – displayName

+0

@IvanStoev: आखिरी चीज जो अब करने की आवश्यकता है वह यह है कि ऊपर दिया गया कोड एक अलग विधि में फैला हुआ है ताकि उसका क्लीनर हो। – displayName

1

यहाँ ऐसा करने के लिए एक अधिक कुशल तरीका है:

var countB = new Dictionary<string, int>(listB.Count); 
foreach (var x in listB) 
{ 
    int count; 
    countB.TryGetValue(x, out count); 
    countB[x] = count + 1; 
} 
listA.RemoveAll(x => 
{ 
    int count; 
    if (!countB.TryGetValue(x, out count)) return false; 
    if (count == 1) 
     countB.Remove(x); 
    else 
     countB[x] = count - 1; 
    return true; 
}); 
+0

आपने उस चरण को याद किया जहां आप * countb * populate *। – displayName

+0

@displayName मैंने नहीं किया - कोशिश करें और देखें (संकेत - छोटी रेखा 'countb [x] = गिनती + 1; ') :) –

+0

ओह मैं देखता हूं ...' TryGetValue()' के इस व्यवहार के बारे में नहीं पता था शब्दकोश में। कुछ नया सीख लिया। – displayName

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