123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- namespace SmartCoalApplication
- {
- /// <summary>
- /// Represents an enumerable collection of items. Each item can only be present
- /// in the collection once. An item's identity is determined by a combination
- /// of the return values from its GetHashCode and Equals methods.
- /// This class is analagous to C++'s std::set template class.
- /// </summary>
- [Serializable]
- public class Set<T>
- : ICloneable,
- ICollection<T>
- {
- private Dictionary<T, object> dictionary;
- public static Set<T> Intersect(Set<T> set1, Set<T> set2)
- {
- Set<T> intersection = new Set<T>();
- foreach (T item in set1)
- {
- if (set2.Contains(item))
- {
- intersection.Add(item);
- }
- }
- return intersection;
- }
- public static Set<T> Union(Set<T> set1, Set<T> set2)
- {
- Set<T> union = new Set<T>(set1);
- foreach (T item in set2)
- {
- if (!union.Contains(item))
- {
- union.Add(item);
- }
- }
- return union;
- }
- public static Set<T> Without(Set<T> withUs, Set<T> withoutUs)
- {
- Set<T> result = new Set<T>();
- foreach (T item in withUs)
- {
- if (!withoutUs.Contains(item))
- {
- result.Add(item);
- }
- }
- return result;
- }
- public static bool AreEqual(Set<T> set1, Set<T> set2)
- {
- if (set1.Count != set2.Count)
- {
- // Can't be equal if sizes are different
- return false;
- }
- if (set1.Count == 0)
- {
- // Empty sets are equal to each other.
- // We know that set1.Count=set2.Count, so no need to check set2.Count for 0 as well.
- return true;
- }
- // At this point we know that either everything in set1 is in set2, or
- // that there is something in set1 which is not in set2.
- foreach (T item in set1)
- {
- if (!set2.Contains(item))
- {
- return false;
- }
- }
- return true;
- }
- public bool IsEqualTo(Set<T> set2)
- {
- return AreEqual(this, set2);
- }
- public bool IsSubsetOf(Set<T> set2)
- {
- foreach (T item in this)
- {
- if (!set2.Contains(item))
- {
- return false;
- }
- }
- return true;
- }
- public Set<T> Without(Set<T> withoutUs)
- {
- return Set<T>.Without(this, withoutUs);
- }
- /// <summary>
- /// Adds an element to the set.
- /// </summary>
- /// <param name="item">The object reference to be included in the set.</param>
- /// <exception cref="ArgumentNullException">item is a null reference</exception>
- /// <exception cref="ArgumentException">item is already in the Set</exception>
- public void Add(T item)
- {
- try
- {
- this.dictionary.Add(item, null);
- }
- catch (ArgumentNullException e1)
- {
- throw e1;
- }
- catch (ArgumentException e2)
- {
- throw e2;
- }
- }
- public void AddRange(IEnumerable<T> items)
- {
- foreach (T item in items)
- {
- Add(item);
- }
- }
- public void AddRange(params T[] items)
- {
- AddRange((IEnumerable<T>)items);
- }
- /// <summary>
- /// Removes an element from the set.
- /// </summary>
- /// <param name="item">The object reference to be excluded from the set.</param>
- /// <exception cref="ArgumentNullException">item is a null reference</exception>
- public bool Remove(T item)
- {
- try
- {
- this.dictionary.Remove(item);
- return true;
- }
- catch (ArgumentNullException)
- {
- return false;
- }
- }
- /// <summary>
- /// Determines whether the Set includes a specific element.
- /// </summary>
- /// <param name="item">The object reference to check for.</param>
- /// <returns>true if the Set includes item, false if it doesn't.</returns>
- /// <exception cref="ArgumentNullException">item is a null reference.</exception>
- public bool Contains(T item)
- {
- try
- {
- return this.dictionary.ContainsKey(item);
- }
- catch (ArgumentNullException e1)
- {
- throw e1;
- }
- }
- /// <summary>
- /// Constructs an empty Set.
- /// </summary>
- public Set()
- {
- this.dictionary = new Dictionary<T, object>();
- }
- /// <summary>
- /// Constructs a Set with data copied from the given list.
- /// </summary>
- /// <param name="cloneMe"></param>
- public Set(IEnumerable<T> cloneMe)
- {
- this.dictionary = new Dictionary<T, object>();
- foreach (T theObject in cloneMe)
- {
- Add(theObject);
- }
- }
- public Set(params T[] items)
- : this((IEnumerable<T>)items)
- {
- }
- /// <summary>
- /// Constructs a copy of a Set.
- /// </summary>
- /// <param name="copyMe">The Set to copy from.</param>
- private Set(Set<T> copyMe)
- {
- this.dictionary = new Dictionary<T, object>(copyMe.dictionary);
- }
- #region IEnumerable<T> Members
- /// <summary>
- /// Returns an IEnumerator that can be used to enumerate through the items in the Set.
- /// </summary>
- /// <returns>An IEnumerator for the Set.</returns>
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this.dictionary.Keys.GetEnumerator();
- }
- public IEnumerator<T> GetEnumerator()
- {
- return this.dictionary.Keys.GetEnumerator();
- }
- #endregion
- public Set<T> Clone()
- {
- return new Set<T>(this);
- }
- #region ICloneable Members
- /// <summary>
- /// Returns a copy of the Set. The elements in the Set are copied by-reference only.
- /// </summary>
- /// <returns></returns>
- object ICloneable.Clone()
- {
- return Clone();
- }
- #endregion
- #region ICollection<T> Members
- /// <summary>
- /// Gets a value indicating whether or not the Set is synchronized (thread-safe).
- /// </summary>
- public bool IsSynchronized
- {
- get
- {
- return false;
- }
- }
- /// <summary>
- /// Gets a value indicating how many elements are contained within the Set.
- /// </summary>
- public int Count
- {
- get
- {
- return this.dictionary.Count;
- }
- }
- /// <summary>
- /// Copies the Set elements to a one-dimensional Array instance at a specified index.
- /// </summary>
- /// <param name="array">The one-dimensional Array that is the destination of the objects copied from the Set. The Array must have zero-based indexing.</param>
- /// <param name="index">The zero-based index in array at which copying begins.</param>
- /// <exception cref="ArgumentNullException">array is a null reference.</exception>
- /// <exception cref="ArgumentOutOfRangeException">index is less than zero.</exception>
- /// <exception cref="ArgumentException">The array is not one-dimensional, or the array could not contain the objects copied to it.</exception>
- /// <exception cref="IndexOutOfRangeException">The Array does not have enough space, starting from the given offset, to contain all the Set's objects.</exception>
- public void CopyTo(T[] array, int index)
- {
- int i = index;
- if (array == null)
- {
- throw new ArgumentNullException("array");
- }
- if (index < 0)
- {
- throw new ArgumentOutOfRangeException("index");
- }
- foreach (T o in this)
- {
- try
- {
- array.SetValue(o, i);
- }
- catch (ArgumentException e1)
- {
- throw e1;
- }
- catch (IndexOutOfRangeException e2)
- {
- throw e2;
- }
- ++i;
- }
- }
- /// <summary>
- /// Gets an object that can be used to synchronize access to the Set.
- /// </summary>
- public object SyncRoot
- {
- get
- {
- return this;
- }
- }
- #endregion
- /// <summary>
- /// Copies the elements of the Set to a new generic array.
- /// </summary>
- /// <returns>An array of object references.</returns>
- public T[] ToArray()
- {
- T[] array = new T[Count];
- int index = 0;
- foreach (T o in this)
- {
- array[index] = o;
- ++index;
- }
- return array;
- }
- #region ICollection<T> Members
- public void Clear()
- {
- this.dictionary = new Dictionary<T, object>();
- }
- public bool IsReadOnly
- {
- get
- {
- return false;
- }
- }
- #endregion
- }
- }
|