लाइनक में संघ बनाम कॉनैट


86

मेरा एक सवाल Unionऔर है Concat। मुझे लगता है कि दोनों ही मामले में एक जैसा व्यवहार कर रहे हैं List<T>

var a1 = (new[] { 1, 2 }).Union(new[] { 1, 2 });             // O/P : 1 2
var a2 = (new[] { 1, 2 }).Concat(new[] { 1, 2 });            // O/P : 1 2 1 2

var a3 = (new[] { "1", "2" }).Union(new[] { "1", "2" });     // O/P : "1" "2"
var a4 = (new[] { "1", "2" }).Concat(new[] { "1", "2" });    // O/P : "1" "2" "1" "2"

उपरोक्त परिणाम अपेक्षित हैं,

लेकिन आई का इन्सेज़ List<T>मुझे वही परिणाम मिल रहा है।

class X
{
    public int ID { get; set; }
}

class X1 : X
{
    public int ID1 { get; set; }
}

class X2 : X
{
    public int ID2 { get; set; }
}

var lstX1 = new List<X1> { new X1 { ID = 10, ID1 = 10 }, new X1 { ID = 10, ID1 = 10 } };
var lstX2 = new List<X2> { new X2 { ID = 10, ID2 = 10 }, new X2 { ID = 10, ID2 = 10 } };

var a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>());     // O/P : a5.Count() = 4
var a6 = lstX1.Cast<X>().Concat(lstX2.Cast<X>());    // O/P : a6.Count() = 4

लेकिन दोनों एक ही तरह का व्यवहार कर रहे हैं List<T>

कृपया कोई सुझाव?


1
यदि आप इन दो तरीकों के बीच अंतर जानते हैं, तो परिणाम आपको आश्चर्यचकित क्यों करता है? यह विधियों की कार्यक्षमता का प्रत्यक्ष परिणाम है।
कोनराड रुडोल्फ

@KonradRudolph, मेरा क्या अर्थ है सूची <T> मैं किसी भी एक 'संघ' / 'कॉन्सेप्ट' का उपयोग कर सकता हूं। क्योंकि दोनों एक जैसा व्यवहार कर रहे हैं।
प्रसाद कानापर्थी

नहीं, जाहिर है। वे वैसा व्यवहार नहीं करते, जैसा आपका पहला उदाहरण दिखाता है।
कोनराड रुडोल्फ

आपके उदाहरण में, सभी आईडी अलग-अलग हैं।
जिम मेंथेल

@JimMischel, मेरे पोस्ट को संपादित किया। समान मूल्यों के साथ भी यह समान व्यवहार कर रहा है।
प्रसाद कानापर्थी

जवाबों:


110

संघ Distinctमूल्य लौटाता है। डिफ़ॉल्ट रूप से यह वस्तुओं के संदर्भों की तुलना करेगा। आपकी वस्तुओं के अलग-अलग संदर्भ हैं, इस प्रकार वे सभी अलग-अलग माने जाते हैं। जब आप आधार प्रकार पर जाते हैं X, तो संदर्भ नहीं बदला जाता है।

यदि आप ओवरराइड करेंगे Equalsऔर GetHashCode(अलग-अलग आइटम का चयन करने के लिए उपयोग किया जाता है), तो आइटम की तुलना संदर्भ से नहीं की जाएगी:

class X
{
    public int ID { get; set; }

    public override bool Equals(object obj)
    {
        X x = obj as X;
        if (x == null)
            return false;
        return x.ID == ID;
    }

    public override int GetHashCode()
    {
        return ID.GetHashCode();
    }
}

लेकिन आपकी सभी वस्तुओं का अलग-अलग मूल्य है ID। इसलिए सभी वस्तुओं को अभी भी अलग माना जाता है। यदि आप एक ही के साथ कई आइटम प्रदान करेंगे, IDतो आप Unionऔर के बीच अंतर देखेंगे Concat:

var lstX1 = new List<X1> { new X1 { ID = 1, ID1 = 10 }, 
                           new X1 { ID = 10, ID1 = 100 } };
var lstX2 = new List<X2> { new X2 { ID = 1, ID2 = 20 }, // ID changed here
                           new X2 { ID = 20, ID2 = 200 } };

var a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>());  // 3 distinct items
var a6 = lstX1.Cast<X>().Concat(lstX2.Cast<X>()); // 4

आपका प्रारंभिक नमूना काम करता है, क्योंकि पूर्णांक मूल्य प्रकार हैं और उनकी तुलना मूल्य से की जाती है।


3
यहां तक ​​कि अगर यह संदर्भों की तुलना नहीं कर रहा था, लेकिन उदाहरण के भीतर आईडी, तब भी चार आइटम होंगे क्योंकि आईडी अलग-अलग हैं।
Rawling

@ सवानी नोप, वे नहीं हैं। मुझे लगता है कि आपने दूसरे संग्रह में पहले आइटम की आईडी नहीं बदली थी, जैसा कि मैंने ऊपर कहा
सर्गेई बेरेज़ोव्स्की

@ शवानी तब आपने इक्वल्स और गेटहॉशकोड को ओवरराइड नहीं किया, जैसा कि मैंने ऊपर कहा
सर्गेई बेरेज़ोवस्की

@lazyberezovsky, मैं आपके उत्तर से सहमत हूं। लेकिन मैं अभी भी टिप्पणियों से खुश नहीं हूं। यदि आप मेरा नमूना कोड निष्पादित करते हैं तो आप 'a5' और 'a6' के लिए एक ही परिणाम देख सकते हैं। मैं समाधान की तलाश में नहीं हूं। लेकिन। कॉनसैट ’और ist यूनियन’ उस सिचुएशन में समान व्यवहार क्यों कर रहे हैं। कृपया उत्तर दें।
प्रसाद कानापर्थी

3
@ शवानी सॉरी, अफाक था। x.Union(y)के रूप में ही है x.Concat(y).Distinct()। इसलिए अंतर केवल आवेदन करने के साथ है Distinct। कैसे लिनक अलग-अलग अनुक्रमों में अलग (यानी अलग) वस्तुओं का चयन करता है? अपने नमूना कोड में (प्रश्न से) Linq संदर्भ द्वारा वस्तुओं की तुलना करता है (यानी स्मृति में पता)। जब आप newऑपरेटर के माध्यम से नई वस्तु बनाते हैं , तो यह नए पते पर मेमोरी आवंटित करता है। इसलिए, जब आपके पास चार नए बनाए गए ऑब्जेक्ट होंगे, तो पते अलग होंगे। और सभी वस्तुएं अलग-अलग होंगी। इस प्रकार Distinctसभी वस्तुओं को अनुक्रम से लौटा देंगे।
सेर्गेई बेरेज़ोवस्की

48

Concatवस्तुतः पहले अनुक्रम से आइटम वापस आते हैं और उसके बाद दूसरे क्रम से आइटम आते हैं। यदि आप Concatदो-आइटम दृश्यों पर उपयोग करते हैं, तो आपको हमेशा 4-आइटम अनुक्रम मिलेगा।

Unionअनिवार्य रूप से Concatपालन ​​किया जाता है Distinct

आपके पहले दो मामलों में, आप 2-आइटम अनुक्रमों के साथ समाप्त होते हैं, क्योंकि उनके बीच, इनपुट स्क्वेंस की प्रत्येक जोड़ी में दो अलग-अलग आइटम हैं।

आपके तीसरे मामले में, आप 4-आइटम अनुक्रम के साथ समाप्त होते हैं क्योंकि आपके दो इनपुट अनुक्रमों में सभी चार आइटम अलग हैं


14

Unionऔर कस्टम के बिना डुप्लिकेट का पता नहीं लगा सकते Concatहैं, उसी के साथ व्यवहार करें । यह सिर्फ देख रहा है कि क्या दोनों एक ही संदर्भ हैं।UnionIEqualityComparer<X>

public class XComparer: IEqualityComparer<X>
{
    public bool Equals(X x1, X x2)
    {
        if (object.ReferenceEquals(x1, x2))
            return true;
        if (x1 == null || x2 == null)
            return false;
        return x1.ID.Equals(x2.ID);
    }

    public int GetHashCode(X x)
    {
        return x.ID.GetHashCode();
    }
}

अब आप इसे ओवरलोड में उपयोग कर सकते हैं Union:

var comparer = new XComparer();
a5 = lstX1.Cast<X>().Union(lstX2.Cast<X>(), new XComparer()); 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.