using System; using System.Collections; using System.Collections.Generic; namespace Vanara.Collections { /// A sparse array based on a dictionary. public class SparseArray : IList { /// Base hash table protected readonly Dictionary hashtable; /// Initializes a new instance of the class. public SparseArray() { hashtable = new Dictionary(); } /// Returns an enumerator that iterates through the collection. /// A that can be used to iterate through the collection. public IEnumerator GetEnumerator() => hashtable.Values.GetEnumerator(); /// Determines whether the array contains the specified value. /// The value. /// true if the array contains the specified value; otherwise, false. public bool Contains(T item) => hashtable.ContainsValue(item); /// Removes all items from the . /// The is read-only. public void Clear() { hashtable.Clear(); } /// Gets the index of the specified item, or returns -1 if item is not in the array. /// The item. /// public int IndexOf(T item) { foreach (var hash in hashtable) { if (hash.Value.Equals(item)) return hash.Key; } return -1; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// Inserts an item to the at the specified index. /// The zero-based index at which should be inserted. /// The object to insert into the . /// is not a valid index in the . /// The is read-only. public void Insert(int index, T item) { if (hashtable.ContainsKey(index)) hashtable[index] = item; else hashtable.Add(index, item); } /// Removes the item at the specified index. /// The zero-based index of the item to remove. /// is not a valid index in the . /// The is read-only. public void RemoveAt(int index) { hashtable.Remove(index); } /// Gets or sets the element at the specified index. /// The index of the element. /// The element at the specified index. public T this[int index] { get => hashtable.TryGetValue(index, out T ret) ? ret : default; set => Insert(index, value); } /// Adds an item to the . /// The object to add to the . /// The is read-only. void ICollection.Add(T item) { throw new NotSupportedException(); } /// /// Copies the elements of the to an , starting at a particular index. /// /// /// The one-dimensional that is the destination of the elements 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 elements 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) { hashtable.Values.CopyTo(array, arrayIndex); } /// Gets the number of elements contained in the . /// The number of elements contained in the . public int Count => hashtable.Count; /// Gets a value indicating whether the is read-only. /// true if the is read-only; otherwise, false. public bool IsReadOnly => false; /// Removes the first occurrence of a specific object from the . /// The object to remove from the . /// /// true if was successfully removed from the ; otherwise, false. This /// method also returns false if is not found in the original . /// /// The is read-only. public bool Remove(T item) { var idx = IndexOf(item); if (idx == -1) return false; RemoveAt(idx); return true; } /// Collapses array into new, condensed array. Does not maintain indexes. /// An array of public T[] ToArray() { var output = new T[hashtable.Values.Count]; hashtable.Values.CopyTo(output, 0); return output; } } }