2010-04-08 15 views
22

मैं एक मल्टीसेट के .NET कार्यान्वयन की तलाश में हूं। क्या कोई अच्छाई सुझा सकता है?क्या नेट के लिए मल्टीसेट का कोई कार्यान्वयन है?

(एक मल्टीसेट, या बैग, एक सेट है जिसमें डुप्लिकेट मान हो सकते हैं, और जिस पर आप सेट ऑपरेशंस कर सकते हैं: चौराहे, अंतर इत्यादि। उदाहरण के लिए एक शॉपिंग कार्ट को मल्टीसेट के रूप में माना जा सकता है क्योंकि आप कर सकते हैं एक ही उत्पाद की कई घटनाएं हैं।)

+0

कृपया देखें:: एक बुनियादी मल्टीसेट इस प्रकार लागू किया जा सकता [? सी # सेट संग्रह] (http://stackoverflow.com/questions/183685/c-set-collection) –

+0

धन्यवाद। कुछ पोस्टर ने विंटेललेक्ट पावर कलेक्शन का उल्लेख किया, जिसमें एक बैग प्रकार है। यह बहुत अच्छा लग रहा है। –

+0

सी 5 सामान भी है, लेकिन मुझे नहीं लगता कि यह सेट ऑपरेशंस लागू करता है। –

उत्तर

4

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

अन्य संभावनाओं का उपयोग केवल List आइटमों का उपयोग करना होगा, जिसमें आप डुप्लिकेट डाल सकते हैं। यह एक शॉपिंग कार्ट के लिए एक बेहतर तरीका हो सकता है।

+0

अच्छा विचार। लेकिन मुझे कुशलतापूर्वक दो सेटों के बीच अंतर खोजने में सक्षम होना चाहिए। अगर मैंने अपना खुद का लुत्फ उठाया, तो मुझे यह सुनिश्चित करने में काफी प्रयास करना होगा कि वह संपत्ति हो। तो मैं ऐसा नहीं करना चाहूंगा। –

+0

गणना के साथ शब्दकोशों के लिए आपका विचार मुझ पर उगाया गया है। मुझे लगता है कि यदि आपके आइटमों में अलग-अलग मूल्य होने की बजाय गणना की गई संपत्ति (जो उनके मामले में होती है) तो यह अच्छी तरह से काम करेगा। अंतर अंतर ओ (एन) होना चाहिए। यदि आपके पास अलग-अलग मूल्य हैं तो एक मल्टीसेट बेहतर होगा। –

1
public class Multiset<T>: ICollection<T> 
{ 
    private readonly Dictionary<T, int> data; 

    public Multiset() 
    { 
     data = new Dictionary<T, int>(); 
    } 

    private Multiset(Dictionary<T, int> data) 
    { 
     this.data = data; 
    } 

    public void Add(T item) 
    { 
     int count = 0; 
     data.TryGetValue(item, out count); 
     count++; 
     data[item] = count; 
    } 

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

    public Multiset<T> Except(Multiset<T> another) 
    { 
     Multiset<T> copy = new Multiset<T>(new Dictionary<T, int>(data)); 
     foreach (KeyValuePair<T, int> kvp in another.data) 
     { 
      int count; 
      if (copy.data.TryGetValue(kvp.Key, out count)) 
      { 
       if (count > kvp.Value) 
       { 
        copy.data[kvp.Key] = count - kvp.Value; 
       } 
       else 
       { 
        copy.data.Remove(kvp.Key); 
       } 
      } 
     } 
     return copy; 
    } 

    public Multiset<T> Intersection(Multiset<T> another) 
    { 
     Dictionary<T, int> newData = new Dictionary<T, int>(); 
     foreach (T t in data.Keys.Intersect(another.data.Keys)) 
     { 
      newData[t] = Math.Min(data[t], another.data[t]); 
     } 
     return new Multiset<T>(newData); 
    } 

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

    public void CopyTo(T[] array, int arrayIndex) 
    { 
     foreach (KeyValuePair<T, int> kvp in data) 
     { 
      for (int i = 0; i < kvp.Value; i++) 
      { 
       array[arrayIndex] = kvp.Key; 
       arrayIndex++; 
      } 
     } 
    } 

    public IEnumerable<T> Mode() 
    { 
     if (!data.Any()) 
     { 
      return Enumerable.Empty<T>(); 
     } 
     int modalFrequency = data.Values.Max(); 
     return data.Where(kvp => kvp.Value == modalFrequency).Select(kvp => kvp.Key); 
    } 

    public int Count 
    { 
     get 
     { 
      return data.Values.Sum(); 
     } 
    } 

    public bool IsReadOnly 
    { 
     get 
     { 
      return false; 
     } 
    } 

    public bool Remove(T item) 
    { 
     int count; 
     if (!data.TryGetValue(item, out count)) 
     { 
      return false; 
     } 
     count--; 
     if (count == 0) 
     { 
      data.Remove(item); 
     } 
     else 
     { 
      data[item] = count; 
     } 
     return true; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     return new MultisetEnumerator<T>(this); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return new MultisetEnumerator<T>(this); 
    } 

    private class MultisetEnumerator<T> : IEnumerator<T> 
    { 
     public MultisetEnumerator(Multiset<T> multiset) 
     { 
      this.multiset = multiset; 
      baseEnumerator = multiset.data.GetEnumerator(); 
      index = 0; 
     } 

     private readonly Multiset<T> multiset; 
     private readonly IEnumerator<KeyValuePair<T, int>> baseEnumerator; 
     private int index; 

     public T Current 
     { 
      get 
      { 
       return baseEnumerator.Current.Key; 
      } 
     } 

     public void Dispose() 
     { 
      baseEnumerator.Dispose(); 
     } 

     object System.Collections.IEnumerator.Current 
     { 
      get 
      { 
       return baseEnumerator.Current.Key; 
      } 
     } 

     public bool MoveNext() 
     { 
      KeyValuePair<T, int> kvp = baseEnumerator.Current; 
      if (index < (kvp.Value - 1)) 
      { 
       index++; 
       return true; 
      } 
      else 
      { 
       bool result = baseEnumerator.MoveNext(); 
       index = 0; 
       return result; 
      } 
     } 

     public void Reset() 
     { 
      baseEnumerator.Reset(); 
     } 
    } 
} 
+0

पुराना धागा, पुराना उत्तर, हाँ, हाँ, मुझे पता है। वैसे भी, आपके पास आपके एन्यूमेरेटर क्लास में नेस्टेड टेम्पलेट तर्क है। आपको इसकी आवश्यकता नहीं है। आप केवल 'निजी श्रेणी मल्टीसेट एनेमेरेटर: आईएन्यूमेरेटर ' का उपयोग कर सकते हैं, क्योंकि टी पहले से ही आंतरिक कक्षा के दायरे में परिभाषित है। – Arshia001

3

किसी भी चीज को स्वयं को मल्टीसेट के सी # कार्यान्वयन को कॉल करना आंतरिक रूप से एक शब्दकोश पर आधारित नहीं होना चाहिए। शब्दकोश हैश टेबल, अनियंत्रित संग्रह हैं। सी ++ के सेट, मल्टीसेट, मानचित्र, और मल्टीमैप्स का ऑर्डर किया जाता है। आंतरिक रूप से प्रत्येक को आत्म-संतुलित बाइनरी खोज पेड़ के कुछ स्वाद के रूप में दर्शाया जाता है।

सी # में हमें हमारे कार्यान्वयन के आधार के रूप में सॉर्टेड डिक्शनरी का उपयोग करना चाहिए जैसा कि माइक्रोसॉफ्ट के अपने दस्तावेज के अनुसार एक सॉर्टेड डिक्शनरी "is a binary search tree with O(log n) retrieval" है।

public class SortedMultiSet<T> : IEnumerable<T> 
{ 
    private SortedDictionary<T, int> _dict; 

    public SortedMultiSet() 
    { 
     _dict = new SortedDictionary<T, int>(); 
    } 

    public SortedMultiSet(IEnumerable<T> items) : this() 
    { 
     Add(items); 
    } 

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

    public void Add(T item) 
    { 
     if (_dict.ContainsKey(item)) 
      _dict[item]++; 
     else 
      _dict[item] = 1; 
    } 

    public void Add(IEnumerable<T> items) 
    { 
     foreach (var item in items) 
      Add(item); 
    } 

    public void Remove(T item) 
    { 
     if (!_dict.ContainsKey(item)) 
      throw new ArgumentException(); 
     if (--_dict[item] == 0) 
      _dict.Remove(item); 
    } 

    // Return the last value in the multiset 
    public T Peek() 
    { 
     if (!_dict.Any()) 
      throw new NullReferenceException(); 
     return _dict.Last().Key; 
    } 

    // Return the last value in the multiset and remove it. 
    public T Pop() 
    { 
     T item = Peek(); 
     Remove(item); 
     return item; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     foreach(var kvp in _dict) 
      for(int i = 0; i < kvp.Value; i++) 
       yield return kvp.Key; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 
} 
+1

सिवाय इसके कि आप किसी को ढूंढने के बाद अगली/पिछली वस्तु पर नहीं जा सकते हैं, और कोई ['equal_range'] नहीं है (http://en.cppreference.com/w/cpp/algorithm/equal_range)। यह वह जगह है जहां सी ++ '(बहु_) सेट' और' (बहु_) नक्शा चमक चमकती है, आप सीमा की शुरुआत और अंत को तेजी से ढूंढ सकते हैं और सीमा में सबकुछ संसाधित कर सकते हैं। – doug65536

+0

मल्टीसेट को सॉर्ट करने के लिए प्रेरणा क्या है? गणितीय अवधारणा का आदेश नहीं दिया गया है। एक 'शब्दकोश' सॉर्ट नहीं किया गया है, लेकिन क्या? –

+0

मल्टीसेट को सॉर्ट करने के लिए प्रेरणा यह है कि सी ++ मानक लाइब्रेरी डेटा स्ट्रक्चर std :: मल्टीसेट का आदेश दिया जाता है, ताकि जब बहुत से लोग यह सुन सकें कि कोई "मल्टीसेट" के .NET कार्यान्वयन की तलाश में है, तो सही नाम, लगता है जैसे कि वे std :: multiset के .NET कार्यान्वयन के लिए पूछ रहे हैं जिसे आदेश दिया जाना आवश्यक है। – jwezorek

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