संग्रह जो .NET में केवल अनन्य आइटम की अनुमति देता है?


103

क्या C # में एक संग्रह है जो आपको इसमें डुप्लिकेट आइटम नहीं जोड़ने देगा? उदाहरण के लिए, मूर्ख वर्ग के साथ

public class Customer {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }

    public override int GetHashCode() {
        return (FirstName + LastName + Address).GetHashCode();
    }

    public override bool Equals(object obj) {
        Customer C = obj as Customer;
        return C != null && String.Equals(this.FirstName, C.FirstName) && String.Equals(this.LastName, C.LastName) && String.Equals(this.Address, C.Address);
    }
}

निम्नलिखित कोड (स्पष्ट रूप से) एक अपवाद फेंक देगा:

Customer Adam = new Customer { Address = "A", FirstName = "Adam", LastName = "" };
Customer AdamDup = new Customer { Address = "A", FirstName = "Adam", LastName = "" };

Dictionary<Customer, bool> CustomerHash = new Dictionary<Customer, bool>();
CustomerHash.Add(Adam, true);
CustomerHash.Add(AdamDup, true);

लेकिन क्या कोई ऐसा वर्ग है जो समान रूप से विशिष्टता की गारंटी देगा, लेकिन बिना KeyValuePairs के? मैंने सोचा था HashSet<T>कि ऐसा होगा, लेकिन डॉक्स को पढ़ने से लगता है कि क्लास सिर्फ एक सेट इंप्लीमेंटेशन ( फिगर ) है।


4
मैं आपकी समस्या को नहीं समझता HashSet<T>। MSDN का कहना है कि "HashSet <T> वर्ग उच्च प्रदर्शन सेट संचालन प्रदान करता है। एक सेट एक संग्रह है जिसमें कोई डुप्लिकेट तत्व नहीं होते हैं, और जिनके तत्व किसी विशेष क्रम में नहीं होते हैं।"
डैनियल हिलगर्थ

5
क्या आप अधिक बता सकते हैं कि HashSet<T>अपर्याप्त क्यों है?
जारेदपर

@ म्यूटिनेटर: Dictionary<K,V>क्लास किसी भी तरह के ऑर्डर की गारंटी नहीं देता है।
ल्यूक

3
मुझे लगता है कि वह केवल एक अपवाद फेंकना चाहता है जब आप एक मौजूदा मूल्य जोड़ने की कोशिश करते हैं ... ऐसा करने के लिए, बस HashSet<T>.Addविधि से लौटाए गए बूल मान की जांच करें और जब फेंकें false...
digEmAll

2
यह भी दृढ़ता से केवल अपरिवर्तनीय प्रकारों के लिए उन्हें अधिभारित करने की अनुशंसा करता है । एक परिवर्तनशील ग्राहक आमतौर पर डिफ़ॉल्ट संदर्भ-समानता के साथ बेहतर होता है।
हेनक होल्टरमैन

जवाबों:


205

HashSet<T>वह है जो आप ढूंढ रहे हैं। से MSDN (जोर जोड़ा):

HashSet<T>वर्ग उच्च प्रदर्शन सेट आपरेशन प्रदान करता है। एक सेट एक संग्रह है जिसमें कोई डुप्लिकेट तत्व नहीं होते हैं , और जिनके तत्व किसी विशेष क्रम में नहीं होते हैं।

ध्यान दें कि HashSet<T>.Add(T item)विधि एक लौटाती है bool- trueयदि आइटम संग्रह में जोड़ा गया था; falseयदि आइटम पहले से मौजूद था।


9
इस मामले में टी आइटम IEquatable इंटरफ़ेस को लागू करना चाहिए। यदि वर्ग इस इंटरफ़ेस को इनहेरिट नहीं करता है, तो HashSet <T> डुप्लिकेट तत्व जोड़ता है।
रुडोल्फ ड्वोरसेक

या आइटम लागू करने के बजाय IEquatable, आप कंस्ट्रक्टर EqualityComparer<T>को उदाहरण के एक (कस्टम) कार्यान्वयन पास कर सकते हैं HashSet<T>
सिप्के शूर्स्त्र

17

कैसे के बारे में सिर्फ एक विस्तार विधि हैशसेट पर?

public static void AddOrThrow<T>(this HashSet<T> hash, T item)
{
    if (!hash.Add(item))
        throw new ValueExistingException();
}

13

HashSet<T>MSDN पर पृष्ठ से :

HashSet (T का वर्ग) उच्च प्रदर्शन सेट संचालन प्रदान करता है। एक सेट एक संग्रह है जिसमें कोई डुप्लिकेट तत्व नहीं होते हैं , और जिनके तत्व किसी विशेष क्रम में नहीं होते हैं।

(जोर मेरा)


4

यदि आप सभी को तत्वों की विशिष्टता सुनिश्चित करना है, तो हैशसेट वही है जो आपको चाहिए।

जब आप कहते हैं कि "सिर्फ एक सेट कार्यान्वयन" का क्या मतलब है? एक सेट अनूठे तत्वों का एक संग्रह है (परिभाषा के अनुसार) जो तत्व क्रम को नहीं बचाता है।


आप पूरी तरह से सही हैं; सवाल बेवकूफ की तरह था। असल में, मैं एक ऐसी चीज की तलाश कर रहा था, जब कोई डुप्लिकेट जोड़े जाने पर एक अपवाद को फेंक देगा (जैसे शब्दकोश <TKey, TValue>), लेकिन जैसा कि पहले ही उल्लेख किया गया है, हशसेट <T> डुप्लिकेट ऐड पर गलत है। +1, शुक्रिया।
एडम रैक्सिस


3

बस मेरे 2 सेंट जोड़ने के लिए ...

अगर आपको ValueExistingException-throwing की आवश्यकता है, तो आप HashSet<T>अपना संग्रह भी आसानी से बना सकते हैं:

public class ThrowingHashSet<T> : ICollection<T>
{
    private HashSet<T> innerHash = new HashSet<T>();

    public void Add(T item)
    {
        if (!innerHash.Add(item))
            throw new ValueExistingException();
    }

    public void Clear()
    {
        innerHash.Clear();
    }

    public bool Contains(T item)
    {
        return innerHash.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        innerHash.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return innerHash.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        return innerHash.Remove(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return innerHash.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

यह उदाहरण के लिए उपयोगी हो सकता है यदि आपको कई स्थानों पर इसकी आवश्यकता हो ...


ज़रूर। मैं सोच रहा था कि कुछ भी बनाया गया था, लेकिन शुक्रिया +1
एडम रैकिस

0

आप कुछ इस प्रकार की विशिष्ट सूची में देख सकते हैं

public class UniqueList<T>
{
    public List<T> List
    {
        get;
        private set;
    }
    List<T> _internalList;

    public static UniqueList<T> NewList
    {
        get
        {
            return new UniqueList<T>();
        }
    }

    private UniqueList()
    {            
        _internalList = new List<T>();
        List = new List<T>();
    }

    public void Add(T value)
    {
        List.Clear();
        _internalList.Add(value);
        List.AddRange(_internalList.Distinct());
        //return List;
    }

    public void Add(params T[] values)
    {
        List.Clear();
        _internalList.AddRange(values);
        List.AddRange(_internalList.Distinct());
       // return List;
    }

    public bool Has(T value)
    {
        return List.Contains(value);
    }
}

और आप इसे इस प्रकार उपयोग कर सकते हैं

var uniquelist = UniqueList<string>.NewList;
uniquelist.Add("abc","def","ghi","jkl","mno");
uniquelist.Add("abc","jkl");
var _myList = uniquelist.List;

केवल तभी "abc","def","ghi","jkl","mno"हमेशा लौटेगा जब डुप्लिकेट को इसमें जोड़ा जाएगा

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