Are there any implementations of multiset for .Net?

后端 未结 3 1240
梦谈多话
梦谈多话 2020-12-18 18:11

I\'m looking for a .Net implementation of a multiset. Can anyone recommend a good one?

(A multiset, or bag, is a set that can have duplicate values, and on which you

3条回答
  •  遥遥无期
    2020-12-18 18:31

    public class Multiset: ICollection
    {
        private readonly Dictionary data;
    
        public Multiset() 
        {
            data = new Dictionary();
        }
    
        private Multiset(Dictionary 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 Except(Multiset another)
        {
            Multiset copy = new Multiset(new Dictionary(data));
            foreach (KeyValuePair 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 Intersection(Multiset another)
        {
            Dictionary newData = new Dictionary();
            foreach (T t in data.Keys.Intersect(another.data.Keys))
            {
                newData[t] = Math.Min(data[t], another.data[t]);
            }
            return new Multiset(newData);
        }
    
        public bool Contains(T item)
        {
            return data.ContainsKey(item);
        }
    
        public void CopyTo(T[] array, int arrayIndex)
        {
            foreach (KeyValuePair kvp in data)
            {
                for (int i = 0; i < kvp.Value; i++)
                {
                    array[arrayIndex] = kvp.Key;
                    arrayIndex++;
                }
            }
        }
    
        public IEnumerable Mode()
        {
            if (!data.Any())
            {
                return Enumerable.Empty();
            }
            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 GetEnumerator()
        {
            return new MultisetEnumerator(this);
        }
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new MultisetEnumerator(this);
        }
    
        private class MultisetEnumerator : IEnumerator
        {
            public MultisetEnumerator(Multiset multiset)
            {
                this.multiset = multiset;
                baseEnumerator = multiset.data.GetEnumerator();
                index = 0;
            }
    
            private readonly Multiset multiset;
            private readonly IEnumerator> 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 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();
            }
        }
    }
    

提交回复
热议问题