// Accord Core Library // The Accord.NET Framework // http://accord-framework.net // // Copyright © César Souza, 2009-2017 // cesarsouza at gmail.com // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; namespace UserControls { /// /// Ordered dictionary. /// /// /// /// This class provides a ordered dictionary implementation for C#/.NET. Unlike the rest /// of the framework, this class is available under a MIT license, so please feel free to /// re-use its source code in your own projects. /// /// /// The types of the keys in the dictionary. /// The type of values in the dictionary. /// [Serializable] internal class OrderedDictionary : IDictionary { private List list; private Dictionary dictionary; /// /// Initializes a new instance of the class. /// public OrderedDictionary() { this.dictionary = new Dictionary(); this.list = new List(); } /// /// Initializes a new instance of the class. /// /// /// The initial number of elements that the can contain. /// public OrderedDictionary(int capacity) { this.dictionary = new Dictionary(capacity); this.list = new List(capacity); } /// /// Initializes a new instance of the class. /// /// /// The IEqualityComparer implementation to use when comparing keys, or null to use /// the default EqualityComparer for the type of the key. /// public OrderedDictionary(IEqualityComparer comparer) { this.dictionary = new Dictionary(comparer); this.list = new List(); } /// /// Initializes a new instance of the class. /// /// /// The initial number of elements that the can contain. /// The IEqualityComparer implementation to use when comparing keys, or null to use /// the default EqualityComparer for the type of the key. /// public OrderedDictionary(int capacity, IEqualityComparer comparer) { this.dictionary = new Dictionary(capacity, comparer); this.list = new List(); } /// /// Initializes a new instance of the class. /// /// /// The System.Collections.Generic.IDictionary`2 whose elements are copied to the /// new . /// public OrderedDictionary(IDictionary dictionary) { this.dictionary = new Dictionary(dictionary); this.list = new List(this.dictionary.Keys); } /// /// Initializes a new instance of the class. /// /// /// The System.Collections.Generic.IDictionary`2 whose elements are copied to the /// new . /// The IEqualityComparer implementation to use when comparing keys, or null to use /// the default EqualityComparer for the type of the key. /// public OrderedDictionary(IDictionary dictionary, IEqualityComparer comparer) { this.dictionary = new Dictionary(dictionary, comparer); this.list = new List(this.dictionary.Keys); } /// /// Gets the at the specified index. /// /// /// The index. /// public TKey GetKeyByIndex(int index) { return list[index]; } /// /// Gets the at the specified index. /// /// /// The index. /// public TValue GetValueByIndex(int index) { return this[GetKeyByIndex(index)]; } /// /// Gets or sets the with the specified key. /// /// /// The key. /// public TValue this[TKey key] { get { return dictionary[key]; } set { dictionary[key] = value; if (!list.Contains(key)) list.Add(key); } } /// /// Gets an containing the keys of the . /// /// /// The keys. /// public ICollection Keys { get { return list; } } /// /// Gets an containing the values in the . /// /// public ICollection Values { get { return list.Select(x => dictionary[x]).ToList(); } } /// /// Gets the number of elements contained in the . /// /// public int Count { get { return dictionary.Count; } } /// /// Gets a value indicating whether the is read-only. /// /// /// true if this instance is read only; otherwise, false. /// public bool IsReadOnly { get { return ((IDictionary)dictionary).IsReadOnly; } } /// /// Adds an element with the provided key and value to the . /// /// /// The object to use as the key of the element to add. /// The object to use as the value of the element to add. /// public void Add(TKey key, TValue value) { dictionary.Add(key, value); if (!list.Contains(key)) list.Add(key); } /// /// Adds an item to the . /// /// /// The object to add to the . /// public void Add(KeyValuePair item) { ((IDictionary)dictionary).Add(item); if (!list.Contains(item.Key)) list.Add(item.Key); } /// /// Replace an element with the provided key and value to the . /// /// /// The object to use as the key of the element to add. /// The object to use as the value of the element to add. /// public bool Replace(TKey oldKey, TKey newKey, Predicate match, TValue value) { if (this.dictionary.Remove(oldKey)) { this.dictionary.Add(newKey, value); // int index = this.list.FindIndex(match); this.list.RemoveAt(index); this.list.Insert(index, newKey); return true; } // return false; } /// /// Removes all items from the . /// /// public void Clear() { dictionary.Clear(); list.Clear(); } /// /// Determines whether the contains a specific value. /// /// /// The object to locate in the . /// /// true if is found in the ; otherwise, false. /// public bool Contains(KeyValuePair item) { return ((IDictionary)dictionary).Contains(item); } /// /// Determines whether the contains an element with the specified key. /// /// /// The key to locate in the . /// /// true if the contains an element with the key; otherwise, false. /// public bool ContainsKey(TKey key) { return dictionary.ContainsKey(key); } /// /// 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. /// public void CopyTo(KeyValuePair[] array, int arrayIndex) { foreach (KeyValuePair pair in this) array[arrayIndex++] = pair; } /// /// Returns an enumerator that iterates through the collection. /// /// /// An enumerator that can be used to iterate through the collection. /// public IEnumerator> GetEnumerator() { foreach (TKey key in list) yield return new KeyValuePair(key, dictionary[key]); } /// /// Removes the element with the specified key from the . /// /// /// The key of the element to remove. /// /// true if the element is successfully removed; otherwise, false. This method also returns false if was not found in the original . /// public bool Remove(TKey key) { if (dictionary.Remove(key)) { list.Remove(key); return true; } return 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 . /// public bool Remove(KeyValuePair item) { if (((IDictionary)dictionary).Remove(item)) { list.Remove(item.Key); return true; } return false; } /// /// Gets the value associated with the specified key. /// /// /// The key whose value to get. /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. /// /// true if the object that implements contains an element with the specified key; otherwise, false. /// public bool TryGetValue(TKey key, out TValue value) { return ((IDictionary)dictionary).TryGetValue(key, out value); } /// /// Returns an enumerator that iterates through a collection. /// /// /// An object that can be used to iterate through the collection. /// IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }