Generic Key/Value pair collection in that preserves insertion order?
不过,我在找字典之类的东西,以保证它能保持插入顺序。因为字典是哈希表,所以我不认为它是哈希表。
是否有用于此的常规集合,或者是否需要使用旧的.NET 1.1集合之一?
没有。但是,System.Collections.Specialized.OrderedDictionary应该解决对它的大多数需求。
编辑:另一个选项是将其转换为通用的。我还没有测试过它,但是它编译了(C 6),应该可以工作。然而,它仍然具有与Ondrej Petrzilka在下面的评论中提到的相同的限制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public class OrderdDictionary<T, K> { public OrderedDictionary UnderlyingCollection { get; } = new OrderedDictionary(); public K this[T key] { get { return (K)UnderlyingCollection[key]; } set { UnderlyingCollection[key] = value; } } public K this[int index] { get { return (K)UnderlyingCollection[index]; } set { UnderlyingCollection[index] = value; } } public ICollection<T> Keys => UnderlyingCollection.Keys.OfType<T>().ToList(); public ICollection<K> Values => UnderlyingCollection.Values.OfType<K>().ToList(); public bool IsReadOnly => UnderlyingCollection.IsReadOnly; public int Count => UnderlyingCollection.Count; public IDictionaryEnumerator GetEnumerator() => UnderlyingCollection.GetEnumerator(); public void Insert(int index, T key, K value) => UnderlyingCollection.Insert(index, key, value); public void RemoveAt(int index) => UnderlyingCollection.RemoveAt(index); public bool Contains(T key) => UnderlyingCollection.Contains(key); public void Add(T key, K value) => UnderlyingCollection.Add(key, value); public void Clear() => UnderlyingCollection.Clear(); public void Remove(T key) => UnderlyingCollection.Remove(key); public void CopyTo(Array array, int index) => UnderlyingCollection.CopyTo(array, index); } |
实际上有一个是通用的,从.NET 2.0开始就存在。它被称为">
如果您需要它作为一个
我对它有一个小问题,那就是它是一个抽象类,您必须对它进行子类化并实现:
1 | protected abstract TKey GetKeyForItem(TItem item) |
号
为此,我宁愿将lambda传递到构造函数中,但同样地,我猜虚拟方法比lambda稍快一些(任何关于此的评论都值得赞赏)。
根据评论中提出的问题进行编辑:
有一个orderedDictionary类,它是一个字典,但可以按插入顺序进行索引,但它不是通用的。目前.NET框架中没有一个通用的。
我在某个地方读到了.NET团队的某个人的评论,他说他们将来可能会实现一个通用版本,但如果是这样的话,它很可能会被称为
编辑:找到报价单。它出现在
This type is actually misnamed; it is not an 'ordered' dictionary as such, but rather an 'indexed' dictionary. Although, today there is no equivalent generic version of this type, if we add one in the future it is likely that we will name such as type 'IndexedDictionary'.
号
好吧,你可以用一个
这里是非通用
这种类型将按插入顺序返回键/值/对序列,很像Ruby2.0散列。
它不需要C 6魔法,符合
在阿德里安的答案中,它的名字是"indexedDictionary"。
YMMV。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; /// <summary> /// A dictionary that maintains insertion ordering of keys. /// /// This is useful for emitting JSON where it is preferable to keep the key ordering /// for various human-friendlier reasons. /// /// There is no support to manually re-order keys or to access keys /// by index without using Keys/Values or the Enumerator (eg). /// </summary> [Serializable] public sealed class IndexedDictionary<TKey, TValue> : IDictionary<TKey, TValue> { // Non-generic version only in .NET 4.5 private readonly OrderedDictionary _backing = new OrderedDictionary(); private IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs { get { return _backing.OfType<DictionaryEntry>() .Select(e => new KeyValuePair<TKey, TValue>((TKey)e.Key, (TValue)e.Value)); } } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return KeyValuePairs.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Add(KeyValuePair<TKey, TValue> item) { _backing[item.Key] = item.Value; } public void Clear() { _backing.Clear(); } public bool Contains(KeyValuePair<TKey, TValue> item) { return _backing.Contains(item.Key); } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { KeyValuePairs.ToList().CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair<TKey, TValue> item) { TValue value; if (TryGetValue(item.Key, out value) && Equals(value, item.Value)) { Remove(item.Key); return true; } return false; } public int Count { get { return _backing.Count; } } public bool IsReadOnly { get { return _backing.IsReadOnly; } } public bool ContainsKey(TKey key) { return _backing.Contains(key); } public void Add(TKey key, TValue value) { _backing.Add(key, value); } public bool Remove(TKey key) { var result = _backing.Contains(key); if (result) { _backing.Remove(key); } return result; } public bool TryGetValue(TKey key, out TValue value) { object foundValue; if ((foundValue = _backing[key]) != null || _backing.Contains(key)) { // Either found with a non-null value, or contained value is null. value = (TValue)foundValue; return true; } value = default(TValue); return false; } public TValue this[TKey key] { get { TValue value; if (TryGetValue(key, out value)) return value; throw new KeyNotFoundException(); } set { _backing[key] = value; } } public ICollection<TKey> Keys { get { return _backing.Keys.OfType<TKey>().ToList(); } } public ICollection<TValue> Values { get { return _backing.Values.OfType<TValue>().ToList(); } } } |
。
在代码项目上有一个通用的实现,它附带了大量的测试用例。
作者选择了一个相当有趣的名字(keyedlist),很难找到。
如果您需要持续复杂的
如果您对第三方代码还满意,请查看我的存储库(许可的MIT许可证):https://github.com/ondrejpetrozilka/rock.collections网站
有
- 基于经典
Dictionary 的源代码(来自.NET核心) - 保留插入顺序并允许手动重新排序
- 功能反向枚举
- 与
Dictionary 具有相同的操作复杂性 Add 和Remove 的操作比Dictionary 慢约20%。- 每个项目多消耗8个字节的内存
保留插入的通用键/值对的另一个选项是使用如下内容:
1 | Queue<KeyValuePair<string, string>> |
这将是一份有保证的订购清单。您可以在一个类似于添加/删除字典而不是调整数组大小的有序区域中排队和出列。它通常可以充当非调整大小的有序(按插入)数组和自动调整大小的无序(按插入)列表之间的中间地带。
我知道你写的是C,但是Java有一个叫做Link KeHHMAP的类,它使用一个私有链接表来维护密钥插入的顺序。如果您找不到合适的通用解决方案,也许这将是您自己实现的开始。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //A SortedDictionary is sorted on the key (not value) System.Collections.Generic.SortedDictionary<string, string> testSortDic = new SortedDictionary<string, string>(); //Add some values with the keys out of order testSortDic.Add("key5","value 1"); testSortDic.Add("key3","value 2"); testSortDic.Add("key2","value 3"); testSortDic.Add("key4","value 4"); testSortDic.Add("key1","value 5"); //Display the elements. foreach (KeyValuePair<string, string> kvp in testSortDic) { Console.WriteLine("Key = {0}, value = {1}", kvp.Key, kvp.Value); } |
输出:
1 2 3 4 5 | Key = key1, value = value 5 Key = key2, value = value 3 Key = key3, value = value 2 Key = key4, value = value 4 Key = key5, value = value 1 |
。