2010-02-01 14 views
11

मैंने सोचा कि मुझे Intersect समझा गया है, लेकिन यह पता चला कि मैं गलत था।सभी अंतरण डेटा खोजें, न केवल अद्वितीय मान

List<int> list1 = new List<int>() { 1, 2, 3, 2, 3}; 
List<int> list2 = new List<int>() { 2, 3, 4, 3, 4}; 

list1.Intersect(list2) =>  2,3 

//But what I want is: 
// => 2,3,2,3,2,3,3 

मैं की तरह एक तरह से समझ सकते हैं:

var intersected = list1.Intersect(list2); 
var list3 = new List<int>(); 
list3.AddRange(list1.Where(I => intersected.Contains(I))); 
list3.AddRange(list2.Where(I => intersected.Contains(I))); 

वहाँ LINQ में एक आसान तरीका है इस लक्ष्य को हासिल करने के लिए है?

मुझे यह बताने की ज़रूरत है कि मुझे परवाह नहीं है कि परिणाम किस क्रम में दिए गए हैं।

2,2,2,3,3,3,3 पूरी तरह ठीक है।

समस्या यह है कि मैं इसे बहुत बड़े संग्रह पर उपयोग कर रहा हूं, इसलिए मुझे दक्षता की आवश्यकता है।

हम वस्तुओं के बारे में बात कर रहे हैं, इनट्स नहीं। स्याही सिर्फ आसान उदाहरण के लिए थे, लेकिन मुझे एहसास हुआ कि इससे कोई फर्क पड़ सकता है।

+0

अपने अपडेटों को देखते हुए, आपकी समस्या को हल करने के लिए और भी अधिक प्रभावी तरीके हो सकते हैं। डेटा के बारे में हमें और बताएं। विशेष रूप से, मुझे इस सवाल में दिलचस्पी है कि आपके बहुत बड़े संग्रह में ज्यादातर अद्वितीय तत्व हैं, या अधिकतर डुप्लिकेट हैं। मुझे यह जानने में भी दिलचस्पी है कि क्या तत्व वास्तव में पूर्णांक हैं, या यदि यह कुछ जटिल प्रकार के लिए स्टैंड-इन है; विशेष रूप से, क्या आपके डेटा पर एक * कुल आदेश * परिभाषित किया गया है? यही है, इस डेटा का एक सेट दिया गया है, क्या एक अद्वितीय, अच्छी तरह से परिभाषित सबसे छोटा सबसे बड़ा आदेश है? –

उत्तर

15

चलिए देखते हैं कि हम निश्चित रूप से आप जो चाहते हैं उसे चित्रित कर सकते हैं या नहीं। अगर मैं ग़लत हूं तो मेरी गलती सुझाएं। आप चाहते हैं: सूची 1 के सभी तत्व, क्रमशः, सूची 2 में भी दिखाई देते हैं, इसके बाद सूची 2 के सभी तत्वों के बाद, यह सूची 1 में भी दिखाई देता है। हाँ?

सीधा लगता है।

return list1.Where(x=>list2.Contains(x)) 
    .Concat(list2.Where(y=>list1.Contains(y))) 
    .ToList(); 

ध्यान दें कि यह बड़ी सूचियों के लिए कुशल नहीं है। यदि सूचियों में प्रत्येक एक हजार आइटम हैं तो यह दो मिलियन तुलना करता है। आप उस स्थिति में कर रहे हैं तो आप परीक्षण सदस्यता के लिए एक अधिक कुशल डेटा संरचना का उपयोग करना चाहते:

list1set = new HashSet(list1); 
list2set = new HashSet(list2); 

return list1.Where(x=>list2set.Contains(x)) 
    .Concat(list2.Where(y=>list1set.Contains(y))) 
    .ToList(); 

जो केवल कुछ हजार की तुलना करता है, लेकिन संभवत: अधिक मेमोरी का उपयोग करता।

+5

आपके LINQ प्रश्न आपके अन्य दो प्रश्नों के समान परिणाम नहीं देते हैं - यदि तत्व ई सूची 1 में एम और एन 2 में होता है, तो इसमें n * m बार होता है, जो वांछित व्यवहार नहीं होता है। – kvb

+2

* उत्कृष्ट पकड़ * @ केवीबी। मैं पूरी तरह से चूक गया क्योंकि दिए गए उदाहरण में, वे भ्रमित रूप से समान दिखते हैं। मैं गलत कोड हटा दूंगा। धन्यवाद! –

+0

हैशसेट के बारे में दिलचस्प। मुझे नहीं पता था कि यह अधिक कुशल था। इसमें देखेंगे! – Peterdk

-1

मुझे विश्वास नहीं है कि अंतर्निहित एपीआई के साथ यह संभव है। लेकिन आप जो परिणाम ढूंढ रहे हैं उसे पाने के लिए आप निम्न का उपयोग कर सकते हैं।

IEnumerable<T> Intersect2<T>(this IEnumerable<T> left, IEnumerable<T> right) { 
    var map = left.ToDictionary(x => x, y => false); 
    foreach (var item in right) { 
    if (map.ContainsKey(item)) { 
     map[item] = true; 
    } 
    } 
    foreach (var cur in left.Concat(right)) { 
    if (map.ContainsKey(cur)) { 
     yield return cur; 
    } 
    } 
} 
1
var set = new HashSet(list1.Intersect(list2)); 
return list1.Concat(list2).Where(i=>set.Contains(i)); 
संबंधित मुद्दे