我看到了一些不同的方法来迭代C#中的字典。有标准的方法吗?
当前回答
一般来说,在没有特定上下文的情况下要求“最佳方式”就像要求什么是最好的颜色?
一方面,有很多颜色,没有最好的颜色。这取决于需求,也常常取决于口味。
另一方面,有很多方法可以在C#中迭代字典,没有最好的方法。这取决于需求,也常常取决于口味。
最直接的方式
foreach (var kvp in items)
{
// key is kvp.Key
doStuff(kvp.Value)
}
如果您只需要值(允许将其称为item,比kvp.value更可读)。
foreach (var item in items.Values)
{
doStuff(item)
}
如果您需要特定的排序顺序
一般来说,初学者对词典的列举顺序感到惊讶。
LINQ提供了一种简洁的语法,允许指定顺序(以及许多其他事情),例如:
foreach (var kvp in items.OrderBy(kvp => kvp.Key))
{
// key is kvp.Key
doStuff(kvp.Value)
}
同样,您可能只需要值。LINQ还提供了一个简洁的解决方案:
直接迭代值(允许将其称为item,比kvp.value更可读)但按按键排序
这里是:
foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
{
doStuff(item)
}
从这些示例中可以看到更多真实世界的用例。如果您不需要特定的订单,只需坚持“最直接的方式”(见上文)!
其他回答
有很多选择。我个人最喜欢的是KeyValuePair
Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here
foreach (KeyValuePair<string,object> kvp in myDictionary)
{
// Do some interesting things
}
您也可以使用键和值集合
有时,如果只需要枚举值,请使用字典的值集合:
foreach(var value in dictionary.Values)
{
// do something with entry.Value only
}
本帖报道称,这是最快的方法:http://alexpinsker.blogspot.hk/2010/02/c-fastest-way-to-iterate-over.html
根据MSDN上的官方文档,迭代字典的标准方法是:
foreach (DictionaryEntry entry in myDictionary)
{
//Read entry.Key and entry.Value here
}
我很感激这个问题已经得到了很多回应,但我想做一点研究。
与在数组等对象上迭代相比,在字典上迭代可能会相当慢。在我的测试中,对数组的迭代耗时0.015003秒,而对字典(元素数量相同)的迭代耗时0.0365073秒,是其2.4倍!尽管我看到了更大的差异。相比之下,List介于0.00215043秒之间。
然而,这就像比较苹果和橙子。我的观点是迭代字典很慢。
字典是为查找而优化的,因此考虑到这一点,我创建了两种方法。一个简单地执行foreach,另一个迭代键然后查找。
public static string Normal(Dictionary<string, string> dictionary)
{
string value;
int count = 0;
foreach (var kvp in dictionary)
{
value = kvp.Value;
count++;
}
return "Normal";
}
这一个加载键并对其进行迭代(我也尝试将键拉入字符串[],但差异可以忽略不计。
public static string Keys(Dictionary<string, string> dictionary)
{
string value;
int count = 0;
foreach (var key in dictionary.Keys)
{
value = dictionary[key];
count++;
}
return "Keys";
}
在本例中,正常的foreach测试花费0.0310062,密钥版本花费0.2205441。加载所有键并迭代所有查找显然要慢很多!
在最后一次测试中,我已经执行了十次迭代,看看使用这里的键是否有任何好处(此时我只是好奇):
这是RunTest方法,如果它可以帮助您可视化正在发生的事情。
private static string RunTest<T>(T dictionary, Func<T, string> function)
{
DateTime start = DateTime.Now;
string name = null;
for (int i = 0; i < 10; i++)
{
name = function(dictionary);
}
DateTime end = DateTime.Now;
var duration = end.Subtract(start);
return string.Format("{0} took {1} seconds", name, duration.TotalSeconds);
}
这里,正常的foreach运行耗时0.2820564秒(大约是单个迭代耗时的十倍——正如您所预期的那样)。按键的迭代耗时2.2249449秒。
编辑添加:阅读其他一些答案让我怀疑如果我使用字典而不是字典会发生什么。在本例中,数组耗时0.0120024秒,列表耗时0.0185037秒,字典耗时0.0465093秒。可以合理地预期,数据类型会对字典的速度产生影响。
我的结论是什么?
如果可以的话,请避免在字典上进行迭代,因为它们比在具有相同数据的数组上进行迭代要慢得多。如果您确实选择遍历字典,不要太聪明,尽管速度较慢,但可能会比使用标准foreach方法做得更糟。
foreach是最快的,如果只迭代___个值,它也会更快