using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ICD.Common.Properties;
namespace ICD.Common.Utils.Collections
{
///
/// A collection containing only unique items.
///
///
public sealed class IcdHashSet : ICollection
{
private readonly Dictionary m_Dict;
#region Properties
///
/// Returns a new, empty hashset.
///
[PublicAPI]
public static IcdHashSet NullSet { get { return new IcdHashSet(); } }
///
/// Gets the number of items contained in the .
///
///
/// The number of items contained in the .
///
public int Count { get { return m_Dict.Count; } }
///
/// Gets a value indicating whether the is read-only.
///
///
/// true if the is read-only; otherwise, false.
///
public bool IsReadOnly { get { return false; } }
#endregion
#region Constructors
///
/// Constructor.
///
public IcdHashSet()
{
m_Dict = new Dictionary();
}
///
/// Constructor.
///
///
public IcdHashSet(IEnumerable items)
: this()
{
if (items == null)
return;
AddRange(items);
}
#endregion
#region Methods
[PublicAPI]
public IcdHashSet Union(IEnumerable set)
{
IcdHashSet unionSet = new IcdHashSet(this);
if (set == null)
return unionSet;
unionSet.AddRange(set);
return unionSet;
}
[PublicAPI]
public IcdHashSet Subtract(IEnumerable set)
{
IcdHashSet subtractSet = new IcdHashSet(this);
if (set == null)
return subtractSet;
foreach (T item in set)
subtractSet.Remove(item);
return subtractSet;
}
[PublicAPI]
public bool IsSubsetOf(IcdHashSet set)
{
IcdHashSet setToCompare = set ?? NullSet;
return this.All(setToCompare.Contains);
}
[PublicAPI]
public IcdHashSet Intersection(IcdHashSet set)
{
IcdHashSet intersectionSet = NullSet;
if (set == null)
return intersectionSet;
foreach (T item in this.Where(set.Contains))
intersectionSet.Add(item);
foreach (T item in set.Where(Contains))
intersectionSet.Add(item);
return intersectionSet;
}
///
/// Returns items that are not common between both sets.
///
///
///
[PublicAPI]
public IcdHashSet NonIntersection(IcdHashSet set)
{
return Subtract(set).Union(set.Subtract(this));
}
[PublicAPI]
public bool IsProperSubsetOf(IcdHashSet set)
{
IcdHashSet setToCompare = set ?? NullSet;
// Is a proper subset if A is a subset of B and A != B
return (IsSubsetOf(setToCompare) && !setToCompare.IsSubsetOf(this));
}
[PublicAPI]
public bool IsSupersetOf(IcdHashSet set)
{
IcdHashSet setToCompare = set ?? NullSet;
return setToCompare.IsSubsetOf(this);
}
[PublicAPI]
public bool IsProperSupersetOf(IcdHashSet set)
{
IcdHashSet setToCompare = set ?? NullSet;
// B is a proper superset of A if B is a superset of A and A != B
return (IsSupersetOf(setToCompare) && !setToCompare.IsSupersetOf(this));
}
#endregion
#region ICollection Members
///
/// Adds the item to the collection. Returns false if the item already exists.
///
///
///
public bool Add(T item)
{
// ReSharper disable CompareNonConstrainedGenericWithNull
if (item == null)
// ReSharper restore CompareNonConstrainedGenericWithNull
throw new ArgumentNullException("item");
if (m_Dict.ContainsKey(item))
return false;
m_Dict[item] = null;
return true;
}
///
/// Adds the item to the collection.
///
///
void ICollection.Add(T item)
{
Add(item);
}
///
/// Adds each of the items in the sequence to the collection.
///
///
public void AddRange(IEnumerable items)
{
foreach (T item in items)
Add(item);
}
///
/// Removes all items from the .
///
/// The is read-only.
public void Clear()
{
m_Dict.Clear();
}
///
/// Returns true if the IcdHashSet contains the given item.
///
///
///
public bool Contains(T item)
{
return m_Dict.ContainsKey(item);
}
///
/// Copies the items of the to an , starting at a particular index.
///
/// The one-dimensional that is the destination of the items copied from . The must have zero-based indexing.The zero-based index in at which copying begins. is null. is less than 0. is multidimensional.-or- is equal to or greater than the length of .-or-The number of items in the source is greater than the available space from to the end of the destination .-or-Type T cannot be cast automatically to the type of the destination .
public void CopyTo(T[] array, int arrayIndex)
{
m_Dict.Keys.CopyTo(array, arrayIndex);
}
///
/// Removes the first occurrence of a specific object from the .
///
///
/// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
///
/// The object to remove from the .The is read-only.
public bool Remove(T item)
{
return m_Dict.Remove(item);
}
#endregion
#region Implementation of IEnumerable
///
/// Returns an enumerator that iterates through the collection.
///
///
/// A that can be used to iterate through the collection.
///
/// 1
public IEnumerator GetEnumerator()
{
return m_Dict.Keys.GetEnumerator();
}
///
/// Returns an enumerator that iterates through a collection.
///
///
/// An object that can be used to iterate through the collection.
///
/// 2
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
}