字典中元素的顺序问题

133

我的问题是关于枚举字典元素的。

// Dictionary definition
private Dictionary<string, string> _Dictionary = new Dictionary<string, string>();

// add values using add

_Dictionary.Add("orange", "1");
_Dictionary.Add("apple", "4");
_Dictionary.Add("cucumber", "6");

// add values using []

_Dictionary["banana"] = 7;
_Dictionary["pineapple"] = 7;

// Now lets see how elements are returned by IEnumerator
foreach (KeyValuePair<string, string> kvp in _Dictionary)
{
  Trace.Write(String.Format("{0}={1}", kvp.Key, kvp.Value));
}

元素将按照它们被添加到集合的顺序进行枚举。我能强制按字母顺序排列吗?


6个回答

151

字典中元素的顺序是不确定的。对于哈希表来说,顺序概念根本没有定义。因此,不要指望按照元素添加到字典中的顺序进行枚举。这不能得到保证。

引自文档

为了枚举的目的,字典中的每个项都被视为一个表示值及其键的KeyValuePair<TKey, TValue>结构。返回项的顺序是未定义的。


6
但是,有OrderedDictionary这个类 - Peter Mortensen

35

你可以始终使用SortedDictionary来实现这一点。请注意,默认情况下,该字典是按键排序的,除非指定了比较器。

我对使用OrderedDictionary持怀疑态度,因为文档中指出:

与SortedDictionary类不同,OrderedDictionary的元素不按键排序。


需要注意的是,SortedDictionary<K,V> 是作为二叉搜索树实现的,这使得它的操作与基于哈希表的 Dictionary<K,V> 有不同的时间和空间复杂度。如果用户需要一个 O(1) 的插入/删除哈希表结构,并且还想按键顺序迭代元素,则应该使用 dict.Keys.OrderBy( k => k ).Select( k => dict[k] )(以 O(n) 空间和 O(n log n) 时间为代价)来代替(OrderBy() 将需要在内部列表中缓冲整个键集合)。 - Dai

32
如果您想对元素进行排序,请使用SortedDictionary。普通的哈希表/字典只在存储布局的某种意义上有序。

12
OrderedDictionary在大多数情况下是错误的。它既不按关键字也不按值排序,而是按内部索引排序。SortedDictionary是用户可以操纵的有序字典(默认按键排序)。 - Offler
4
这个问题询问如何按字母顺序排序(假设提问者在谈论键)。如果我理解文档正确的话,有序字典会按照插入的顺序输出元素,即不是按字母顺序排序,而是使用内部索引。SortedDictionary可能是最适合用户问题的选择。 - mattpm

15

对于OrderedDictionary:

 var _OrderedDictionary = new System.Collections.Specialized.OrderedDictionary();

_OrderedDictionary.Add("testKey1", "testValue1");
_OrderedDictionary.Add("testKey2", "testValue2");
_OrderedDictionary.Add("testKey3", "testValue3");

var k = _OrderedDictionary.Keys.GetEnumerator();
var v = _OrderedDictionary.Values.GetEnumerator();

while (k.MoveNext() && v.MoveNext()) {
    var key = k.Current; var value = v.Current;
}

项目将按照它们添加的顺序返回。


14

字典中存储的物品将按照它们在物理上存储的顺序返回,这取决于哈希码和添加物品的顺序。因此,顺序似乎是随机的,并且随着实现的更改,您永远不应该依赖于顺序保持不变。

您可以在枚举这些项时对它们进行排序:

foreach (KeyValuePair<string, string> kvp in _Dictionary.OrderBy(k => k.Value)) {
  ...
}

在框架2.0中,您需要先将项目放入列表中以便对它们进行排序:

List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>(_Dictionary);
items.Sort(delegate(KeyValuePair<string, string> x, KeyValuePair<string, string> y) { return x.Value.CompareTo(y.Value); });
foreach (KeyValuePair<string,string> kvp in items) {
  ...
}

5

关联数组(也称哈希表)是无序的,这意味着元素可以按任何想象的方式排序。

然而,您可以获取数组键(仅键),通过排序函数按字母顺序排序,然后对其进行操作。

我不能给您一个C#示例,因为我不知道这种语言,但这应该足以让您自己继续。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接