2010-12-04 16 views
20

मैं सूची में पूर्णांक के जोड़े कैसे स्टोर कर सकता हूं? मैं जानता हूँ कि मैं की तरह उनके लिए एक वर्ग बना सकता है:सूची में इंक की जोड़ी भंडारण

class Pair 
{ 
    int i1,i2; 
} 

लेकिन अगर मैं ऐसा है कि मैं अगर किसी दिए गए जोड़ी सूची में है की जाँच करने के Contains समारोह उपयोग करने में सक्षम नहीं हूँ। मैं ऐसा कैसे कर सकता हूं ताकि मैं आसानी से सूची में पूर्णांक स्टोर कर सकूं और जांच कर सकूं कि पूर्णांक की एक जोड़ी पहले से मौजूद है या नहीं? मैं टेबल का उपयोग नहीं कर सकता क्योंकि यह ज्ञात नहीं है कि कितने जोड़े होंगे।

संपादित करें:
जोड़ने के लिए भूल: मेरा कार्यक्रम जोड़े (एक्स, वाई) और में (y, x) के बराबर होती है के रूप में इलाज किया जाना है।

संपादित करें:
(एक्स, वाई) और (y, x) कर रहे हैं बराबर की जाँच करते समय यदि Point सूची में है, लेकिन x और y बदली नहीं जा सकता क्योंकि x और y दो अंक के बीच एक कनेक्शन का प्रतिनिधित्व (पूर्णांक बिंदु की आईडी है, और नहीं, मैं किसी भी संदर्भ आदि का उपयोग नहीं कर सकता ...)। जब मैं जांच कर रहा हूं कि List में कोई कनेक्शन है तो यह महत्वपूर्ण नहीं है यदि यह (x, y) या (y, x) है लेकिन बाद में मुझे उस जानकारी की आवश्यकता होगी।

उत्तर

38

आप .NET 4.0 का उपयोग कर रहे हैं, तो आप में

var tuple = new Tuple<int, int>(17, 42); 
var otherTuple = Tuple.Create(17, 42); 

और

var list = new List<Tuple<int, int>>(); 

नोट के रूप में Tuple वर्ग इस्तेमाल कर सकते हैं कि अगर आप Tuple<int, int> का उपयोग करने का तरीका अपनाते हैं तो आप की आवश्यकता होगी को (y, x) के बराबर माना जाने वाला आपके समानता नियमों को दर्शाने के लिए IEqualityComparer<Tuple<TFirst, TSecond>> का एक कस्टम कार्यान्वयन तैयार करने के लिए। इसके बाद आपको इस तुलनात्मक के उदाहरण को List<T>.Contains(T, IEqualityComparer<T>) पर पास करना होगा (यहां T आपके लिए Tuple<int, int> है)।

class TupleAsUnorderedPairComparer : IEqualityComparer<Tuple<TFirst, TSecond>> { 
    public bool Equals(Tuple<TFirst, TSecond> x, Tuple<TFirst, TSecond> y) { 
     if(Object.ReferenceEquals(x, y)) { 
      return true; 
     } 
     if(x == null || y == null) { 
      return false; 
     } 
     return x.Item1 == y.Item1 && x.Item2 == y.Item2 || 
       x.Item1 == y.Item2 && x.Item2 == y.Item1; 
    } 

    public int GetHashCode(Tuple<TFirst, TSecond> x) { 
     if(x == null) { 
      return 0; 
     } 
     return x.Item1.GetHashCode()^x.Item2.GetHashCode(); 
    } 
} 

अन्यथा, आप नहीं कर सकते हैं या नहीं Tuple उपयोग करना चाहते हैं तो आप अपने Pair वर्ग के लिए एक IEqualityComparer<Pair> लागू करने या Object.Equals और Object.GetHashCode ओवरराइड करने के लिए की आवश्यकता होगी।

class Pair { 
    public int First { get; private set; } 
    public int Second { get; private set; } 
    public Pair(int first, int second) { 
     this.First = first; 
     this.Second = second; 
    } 

    public override bool Equals(object obj) { 
     if(Object.ReferenceEquals(this, obj)) { 
      return true; 
     } 
     Pair instance = obj as Pair; 
     if(instance == null) { 
      return false; 
     } 
     return this.First == instance.First && this.Second == instance.Second || 
       this.First == instance.Second && this.Second == instance.First; 
    } 

    public override int GetHashCode() { 
     return this.First.GetHashCode()^this.Second.GetHashCode(); 
    } 
} 

और

class PairEqualityComparer : IEqualityComparer<Pair> { 
    // details elided 
} 

आप उपयोग

list.Contains(pair); 

तो यह Equals और GetHashCode का उपयोग करेगा, लेकिन यदि आप

list.Contains(pair, new PairEqualityComparer); 

का उपयोग तो यहका उपयोग करेगा तोऔर PairEqualityComparer.GetHashCode। ध्यान दें कि ये Object.Equals और Object.GetHashCode के कार्यान्वयन से अलग हो सकते हैं।

अंत में, अगर रोकथाम के लिए परीक्षण ऐसा कुछ है जो आप अक्सर करेंगे तो List आपकी सबसे अच्छी शर्त नहीं है; आपको HashSet जैसे उस उद्देश्य के लिए डिज़ाइन की गई कक्षा का उपयोग करना चाहिए।

+0

मैंने '(x, y) 'के लिए आपकी आवश्यकता को प्रतिबिंबित करने के लिए मेरा उत्तर संपादित किया गया है जिसे' (y, x) 'के बराबर माना जा सकता है। – jason

2

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

आपके पास कक्षा बनाने के लिए सबसे आसान तरीका होगा और फिर List<T> ऑब्जेक्ट पर विधि बनाएं और विस्तार करें।

public static bool ContainsIntegers(this List<Pair> targetList, Pair comparer) { 
    foreach(Pair pair in targetList) 
    { 
     if(pair.i1 == comparer.i1 && pair.i2 == comparer.i2) return true; 
    } 
    return false; 
} 
1

यह करने के लिए एक List<ulong> उपयोग करने के लिए किया जाएगा एक और तरीका है, ऊपरी 32 बिट में सबसे बड़ी संख्या है और कम 32 बिट में अन्य नंबर लगा कर पॉप्युलेट:

ulong MakeEntry(int i1, int i2) 
{ 
    ulong hi = (ulong)Math.Max(i1, i2); 
    ulong lo = (ulong)Math.Min(i1, i2); 
    return (hi << 32) | lo; 
} 

List<ulong> items = new List<ulong>(); 

void DoSomething() 
{ 
    // get numbers i1 and i2 
    // and add to the list 
    items.Add(MakeEntry(i1, i2)); 

    // test to see if the pair is in the list 
    if (items.Contains(MakeEntry(i1, i2))) 
    { 
     // do whatever 
    } 
} 
+0

यह '(x, y)' की आवश्यकता के कारण काम नहीं करता है '(y, x) 'के बराबर माना जाता है। यही है, ओपी _ordered_ जोड़े के विपरीत _unordered_ जोड़े का उपयोग कर रहा है। – jason

+0

@ जेसन: हुह? 'MakeEntry' विधि में न्यूनतम/अधिकतम सुनिश्चित करता है कि (x, y) और (y, x) समान रूप से व्यवहार किए जाते हैं। सबसे बड़ा हमेशा उच्च-आदेश बिट्स में होता है। –

+0

जबकि यह समाधान (x, y) के बराबर (y, x) के बराबर व्यवहार करेगा, यह दो मानों को स्वैप करके ऐसा करता है। यह मुझे स्पष्ट नहीं है कि ओपी चाहता है कि i1 और i2 व्यक्तिगत रूप से सुलभ हो। यदि ऐसा है, तो यह समाधान काम नहीं करेगा। –

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