2009-08-07 9 views
118

मैं HashSet<T> प्रकार की खोज कर रहा हूं, लेकिन मुझे समझ में नहीं आता कि यह संग्रह में कहां खड़ा है।मुझे हैशसेट <T> प्रकार का उपयोग कब करना चाहिए?

क्या कोई इसे List<T> को प्रतिस्थापित करने के लिए उपयोग कर सकता है? मैं बेहतर होने के लिए HashSet<T> के प्रदर्शन की कल्पना करता हूं, लेकिन मैं इसके तत्वों तक व्यक्तिगत पहुंच नहीं देख सका।

क्या यह केवल गणना के लिए है?

उत्तर

213

महत्वपूर्ण बात के बारे HashSet<T> नाम पर सही नहीं है: यह एक सेट है। एक ही सेट के साथ आप केवल एक ही चीज कर सकते हैं यह निर्धारित करना है कि उसके सदस्य क्या हैं, और यह जांचने के लिए कि कोई आइटम सदस्य है या नहीं।

यह पूछने पर कि क्या आप एक तत्व पुनर्प्राप्त कर सकते हैं (उदा। set[45]) सेट की अवधारणा को गलत समझ रहा है। एक सेट के 45 वें तत्व जैसी कोई चीज नहीं है। एक सेट में आइटम के पास कोई ऑर्डर नहीं है। सेट {1, 2, 3} और {2, 3, 1} प्रत्येक सम्मान में समान हैं क्योंकि उनके पास समान सदस्यता है, और सदस्यता सभी महत्वपूर्ण है।

HashSet<T> पर पुनरावृत्ति करना कुछ हद तक खतरनाक है क्योंकि ऐसा करने से सेट में आइटम पर ऑर्डर लगाया जाता है। वह आदेश वास्तव में सेट की संपत्ति नहीं है। आपको इस पर भरोसा नहीं करना चाहिए। यदि संग्रह में वस्तुओं का ऑर्डर करना आपके लिए महत्वपूर्ण है, तो वह संग्रह एक सेट नहीं है।

सेट वास्तव में सीमित हैं और अद्वितीय सदस्यों के साथ हैं। दूसरी तरफ, वे वास्तव में तेज़ हैं।

UnrealScript फ़ाइलों के लिए मेरी वाक्य रचना हाइलाइटर का एक हिस्सा एक नई सुविधा है highlights Doxygen-style comments है:

+1

तथ्य यह है कि ढांचा 'सॉर्टेडसेट' डेटा संरचना प्रदान करता है या तो आप एक सेट की संपत्ति नहीं होने के बारे में जो कहते हैं उसके विपरीत है - या विकास टीम से गलतफहमी के बारे में बताता है। – Veverke

+4

मुझे लगता है कि यह कहना सही है कि 'हैशसेट' में वस्तुओं का क्रम परिभाषित नहीं किया गया है, इसलिए पुनरावर्तक के आदेश पर भरोसा न करें। यदि आप सेट को फिर से सेट करते हैं क्योंकि आप सेट में आइटम्स के खिलाफ कुछ कर रहे हैं, तो यह * खतरनाक नहीं है * जब तक कि आप आदेश से संबंधित किसी भी चीज़ पर भरोसा नहीं कर रहे हैं। 'सॉर्टेडसेट' में 'हैशसेट' * प्लस * ऑर्डर के सभी गुण हैं, हालांकि 'सॉर्टसेटसेट' 'हैशसेट 'से प्राप्त नहीं होता है; rephrased, * एक सॉर्टेडसेट विशिष्ट वस्तुओं * का एक आदेशित संग्रह है। – Kit

+0

मुझे यह जवाब बहुत पसंद है। लेकिन आप इसे पेश करते समय पागल/निराश/परेशान लगते हैं .... जो मैं एक बड़ा प्रशंसक नहीं हूं। – pimbrouwers

11

हैशसेट हैशिंग द्वारा लागू किया गया है। एक सेट उन मानों का संग्रह होता है जिनमें कोई डुप्लिकेट तत्व नहीं होते हैं। एक सेट में मूल्य भी आम तौर पर unordered हैं। तो नहीं, किसी सूची को प्रतिस्थापित करने के लिए एक सेट का उपयोग नहीं किया जा सकता है (जब तक कि आपको पहले स्थान पर सेट का उपयोग नहीं करना चाहिए)।

यदि आप सोच रहे हैं कि एक सेट कितना अच्छा हो सकता है: कहीं भी आप डुप्लीकेट से छुटकारा पाने के लिए चाहते हैं, जाहिर है। थोड़ा सा उदाहरण के रूप में, मान लें कि आपके पास सॉफ़्टवेयर प्रोजेक्ट के 10.000 संशोधन की एक सूची है, और आप यह जानना चाहते हैं कि उस प्रोजेक्ट में कितने लोग योगदान करते हैं। आप Set<string> का उपयोग कर सकते हैं और संशोधन की सूची में पुन: प्रयास कर सकते हैं और प्रत्येक संशोधन के लेखक को सेट में जोड़ सकते हैं। एक बार जब आप इसे फिर से पूरा कर लेंगे, तो सेट का आकार वह उत्तर है जिसे आप ढूंढ रहे थे।

+0

लेकिन सेट एकल तत्वों को पुनर्प्राप्त करने की अनुमति नहीं देता है? सेट की तरह [45]? –

+2

इसके लिए, आप सेट सदस्यों के ऊपर फिर से शुरू करेंगे। अन्य सामान्य संचालन जांच कर रहे हैं कि सेट में कोई तत्व है या सेट का आकार प्राप्त हो रहा है या नहीं। – earl

14

प्रदर्शन सूची पर हैशसेट चुनने का एक बुरा कारण होगा। इसके बजाय, आपके इरादे को बेहतर तरीके से कैप्चर करता है? अगर आदेश महत्वपूर्ण है, तो सेट (या हैशसेट) बाहर है। यदि डुप्लीकेट की अनुमति है, वैसे भी। लेकिन बहुत सारी परिस्थितियां हैं जब हमें आदेश की परवाह नहीं होती है, और हमारे पास डुप्लीकेट नहीं होते - और वह तब होता है जब आप सेट चाहते हैं।

+16

'प्रदर्शन सूची पर हैशसेट चुनने का एक बुरा कारण होगा: मैं बस आपसे सहमत नहीं हूं। यह कहने की तरह है कि दो सूचियों के बजाय डिक्शनरी चुनना प्रदर्शन में मदद नहीं करता है। [निम्नलिखित आलेख] पर एक नज़र डालें (http://geekswithblogs.net/BlackRabbitCoder/archive/2011/02/03/c.net-little-wonders-the-useful-but-overlooked-sets.aspx) –

+11

@ ऑस्कर: मैंने यह नहीं कहा कि सेट तेजी से नहीं हैं - मैंने कहा कि उन्हें चुनने का एक बुरा आधार होगा। यदि आप एक आदेशित संग्रह का प्रतिनिधित्व करने की कोशिश कर रहे हैं, तो एक सेट बस काम नहीं करेगा और इसमें शूहोर्न करने की कोशिश करने की गलती होगी; यदि आपके इच्छित संग्रह में कोई ऑर्डर नहीं है, तो एक सेट सही है - और तेज़। लेकिन पहला सवाल क्या है: आप क्या प्रतिनिधित्व करने की कोशिश कर रहे हैं? –

+2

लेकिन इसके बारे में सोचें। यदि आप यह जांचना चाहते हैं कि दिए गए तार 10,000 स्ट्रिंग्स के कुछ संग्रह के सदस्य हैं, तकनीकी रूप से, 'स्ट्रिंग []। इसमें' और 'हैशसेट शामिल हैं। आपके इरादे को समान रूप से व्यक्त करें; हैशसेट चुनने का कारण यह बहुत तेज़ होगा। – Casey

4

HashSet<T> .NET फ्रेमवर्क में एक डेटा strucutre है जो किसी ऑब्जेक्ट के रूप में mathematical set का प्रतिनिधित्व करने में सक्षम है। इस मामले में, यह सेट तत्वों की समानता की तुलना करने के लिए हैश कोड (प्रत्येक आइटम का GetHashCode परिणाम) का उपयोग करता है।

एक सेट एक सूची से अलग है जिसमें यह केवल उसी तत्व के एक तत्व की अनुमति देता है। HashSet<T> यदि आप दूसरा समान तत्व जोड़ने का प्रयास करते हैं तो false वापस लौटेंगे। वास्तव में, तत्वों की तलाश बहुत तेज है (O(1) समय), क्योंकि आंतरिक डेटा संरचना केवल एक हैशटेबल है।

आप जो उपयोग करने के लिए सोच रहे हैं, ध्यान दें कि एक List<T> उचित जहां HashSet<T> है का उपयोग करते हुए सबसे बड़ी गलती नहीं है, हालांकि यह संभावित है जहाँ आप अपने संग्रह में अवांछनीय डुप्लिकेट आइटम नहीं हैं समस्याओं अनुमति दे सकता है। और क्या है, लुकअप (आइटम पुनर्प्राप्ति) काफी अधिक कुशल है - आदर्श O(1) (सही बाल्टी के लिए) O(n) समय के बजाय - जो कई परिदृश्यों में काफी महत्वपूर्ण है।

+1

किसी सेट में मौजूदा आइटम जोड़ना अपवाद नहीं फेंक देगा। जोड़ें बस झूठी वापसी होगी।इसके अलावा: तकनीकी रूप से हैश लुकअप ओ (एन) है, ओ (1) नहीं, जब तक कि आपके पास एक परिपूर्ण हैशिंग फ़ंक्शन न हो। निश्चित रूप से अभ्यास में आप यह मान लेंगे कि यह ओ (1) है जब तक कि हैशिंग फ़ंक्शन वास्तव में खराब न हो। – sepp2k

+1

@ sepp2k: हाँ, तो यह एक बुलियन लौटाता है ... बिंदु यह है कि यह आपको सूचित करता है। और हैश देखो * सबसे खराब मामला * ओ (एन) यदि आप बाल्टी कर रहे हैं तो भयानक है - यह सामान्य रूप से ओ (1) के बहुत करीब है। – Noldorin

4

List<T> जानकारी के आदेशित सेट स्टोर करने के लिए उपयोग किया जाता है। यदि आप सूची के तत्वों के सापेक्ष आदेश को जानते हैं, तो आप उन्हें निरंतर समय तक एक्सेस कर सकते हैं। हालांकि, यह निर्धारित करने के लिए कि सूची में कोई तत्व कहां है या यह जांचने के लिए कि सूची में मौजूद है या नहीं, लुकअप समय रैखिक है। दूसरी तरफ, HashedSet<T> संग्रहीत डेटा के आदेश की कोई गारंटी नहीं देता है और इसके परिणामस्वरूप इसके तत्वों के लिए लगातार पहुंच का समय प्रदान करता है।

जैसा कि नाम का तात्पर्य है, HashedSet<T> एक डेटा संरचना है जो set semantics लागू करती है। डेटा संरचना को सेट ऑपरेशंस (यानी संघ, अंतर, अंतर) को लागू करने के लिए अनुकूलित किया गया है, जिसे पारंपरिक सूची कार्यान्वयन के साथ कुशलता से नहीं किया जा सकता है।

तो, यह चुनने के लिए कि कौन सा डेटा प्रकार वास्तव में उपयोग करना है, इस पर निर्भर करता है कि आप अपने आवेदन के साथ क्या करने का प्रयास कर रहे हैं।यदि आपको इस बात की कोई परवाह नहीं है कि आपके तत्वों को संग्रह में कैसे आदेश दिया गया है, और केवल अस्तित्व के लिए गणना करना या जांचना चाहते हैं, तो HashSet<T> का उपयोग करें। अन्यथा, List<T> या अन्य उपयुक्त डेटा संरचना का उपयोग करने पर विचार करें।

+2

एक और चेतावनी: सेट आम तौर पर तत्व की केवल एक घटना की अनुमति देता है। –

6

शायद हैशसेट्स के लिए सबसे आम उपयोग यह देखने के लिए है कि उनमें एक निश्चित तत्व है, जो उनके लिए ओ (1) ऑपरेशन के करीब है (पर्याप्त मजबूत हैशिंग फ़ंक्शन मानते हुए), जिनके लिए चेक के लिए चेक समावेशन ओ (एन) (और क्रमबद्ध सेट है जिसके लिए यह ओ है (लॉग एन))। तो यदि आप बहुत सारे चेक करते हैं, चाहे किसी आइटम में कोई आइटम निहित है, हैहसेट्स प्रदर्शन में सुधार हो सकता है। यदि आप केवल उन पर फिर से सक्रिय हो जाते हैं, तो बहुत अंतर नहीं होगा (पूरे सेट पर पुनरावृत्ति ओ (एन) है, सूचियों के साथ ही है और आइटम जोड़ने के दौरान हैशसेट्स कुछ हद तक ऊपर की ओर है)।

और नहीं, आप एक सेट को इंडेक्स नहीं कर सकते हैं, जो किसी भी तरह से समझ में नहीं आता है, क्योंकि सेट का आदेश नहीं दिया जाता है। यदि आप कुछ आइटम जोड़ते हैं, तो सेट याद नहीं करेगा कि कौन सा पहला था, और कौन सा दूसरा आदि

+0

यदि आप केवल उन पर फिर से प्रयास करते हैं तो हैशसेट विधि सूची की तुलना में स्मृति उपयोग का थोड़ा सा जोड़ती है। – SamuelWarren

1

संक्षेप में - किसी भी समय आप एक शब्दकोश का उपयोग करने के लिए लुभाने वाले होते हैं (या एक शब्दकोश जहां एस टी की संपत्ति है) यदि आप एक HashSet पर विचार करना चाहिए (या HashSet टी जो एस पर बराबर पर IEquatable को लागू करने +)

+5

जब तक आप कुंजी की परवाह नहीं करते हैं, तो आपको शब्दकोश का उपयोग करना चाहिए। – Hardwareguy

94

यहाँ मैं जहां का प्रयोग कर एक HashSet<string> की एक वास्तविक उदाहरण है। मुझे यह बताने में सक्षम होना चाहिए कि @ या \ कमांड यह निर्धारित करने के लिए मान्य है कि इसे ग्रे (वैध) या लाल (अमान्य) में दिखाना है या नहीं। मेरे पास सभी वैध आदेशों का HashSet<string> है, इसलिए जब भी मैं लेक्सर में @xxx टोकन दबाता हूं, तो मैं अपने ओ (1) वैधता जांच के रूप में validCommands.Contains(tokenText) का उपयोग करता हूं। मान्य आदेशों के में कमांड के अस्तित्व को छोड़कर मुझे वास्तव में कुछ भी परवाह नहीं है। आइए उन विकल्पों को देखें जिन पर मुझे सामना करना पड़ा:

  • Dictionary<string, ?>: मैं मूल्य के लिए किस प्रकार का उपयोग करता हूं? मान व्यर्थ है क्योंकि मैं अभी ContainsKey का उपयोग करने जा रहा हूं। नोट: .NET 3.0 से पहले यह ओ (1) लुकअप के लिए एकमात्र विकल्प था - HashSet<T> 3.0 के लिए जोड़ा गया था और 4.0 के लिए ISet<T> लागू करने के लिए बढ़ाया गया था।
  • List<string>: यदि मैं सूची क्रमबद्ध रखता हूं, तो मैं BinarySearch का उपयोग कर सकता हूं, जो ओ (लॉग एन) है (ऊपर वर्णित इस तथ्य को नहीं देखा गया है)।हालांकि, चूंकि वैध आदेशों की मेरी सूची एक निश्चित सूची है जो कभी भी नहीं बदली है, यह कभी भी अधिक उपयुक्त नहीं होगी ...
  • string[]: फिर, Array.BinarySearch ओ (लॉग एन) प्रदर्शन देता है। यदि सूची कम है, तो यह सबसे अच्छा प्रदर्शन विकल्प हो सकता है। HashSet, Dictionary, या List की तुलना में इसमें हमेशा कम स्थान ओवरहेड होता है। यहां तक ​​कि BinarySearch के साथ, यह बड़े सेट के लिए तेज़ नहीं है, लेकिन छोटे सेटों के लिए यह प्रयोग करने योग्य होगा। हालांकि मेरे पास कई सौ वस्तुएं हैं, इसलिए मैंने इस पर पारित किया।
+6

असली दुनिया के उदाहरण के लिए धन्यवाद –

23

एक HashSet<T> लागू करता ICollection<T> इंटरफ़ेस:

public interface ICollection<T> : IEnumerable<T>, IEnumerable 
{ 
    // Methods 
    void Add(T item); 
    void Clear(); 
    bool Contains(T item); 
    void CopyTo(T[] array, int arrayIndex); 
    bool Remove(T item); 

    // Properties 
    int Count { get; } 
    bool IsReadOnly { get; } 
} 

एक List<T> औजार IList<T>, जो ICollection<T>

public interface IList<T> : ICollection<T> 
{ 
    // Methods 
    int IndexOf(T item); 
    void Insert(int index, T item); 
    void RemoveAt(int index); 

    // Properties 
    T this[int index] { get; set; } 
} 

एक HashSet फैली अर्थ विज्ञान की स्थापना की है, एक hashtable आंतरिक रूप से के माध्यम से कार्यान्वित किया:

एक सेट एक संग्रह है जिसमें डुप्लिकेट तत्व नहीं हैं, और जिनके तत्व किसी विशेष क्रम में नहीं हैं।

हैशसेट लाभ क्या होता है, अगर यह सूचकांक/स्थिति/सूची व्यवहार खो देता है?

हैशसेट से वस्तुओं को जोड़ना और पुनर्प्राप्त करना हमेशा ऑब्जेक्टर के माध्यम से, और ओ (1) ऑपरेशन के करीब है (सूची ओ (1) ऐड, ओ (1) इंडेक्स द्वारा पुनर्प्राप्त, ओ (एन) ढूंढें/निकालें)।

ए हैशसेट के व्यवहार की तुलना Dictionary<TKey,TValue> का उपयोग करके मूल्यों के रूप में केवल कुंजी जोड़ने/हटाने और शब्दकोश मूल्यों को अनदेखा करके की जा सकती है। आप एक शब्दकोश में कुंजी को डुप्लिकेट मान नहीं होने की उम्मीद करेंगे, और यह "सेट" भाग का बिंदु है।

6

हैशसेट का उपयोग IENumerble संग्रह में डुप्लिकेट तत्वों को निकालने के लिए किया जाएगा। उदाहरण के लिए,

List<string> duplicatedEnumrableStrings = new List<string> {"abc", "ghjr", "abc", "abc", "yre", "obm", "ghir", "qwrt", "abc", "vyeu"}; 
HashSet<string> uniqueStrings = new HashSet(duplicatedEnumrableStrings); 

के बाद उन कोड चलाए जा रहे हैं, uniqueStrings { "abc", "ghjr", "yre", "OBM", "qwrt", "vyeu"} रखती है;

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