CSharp - 在C#什么是最好的方法来遍历一个Dictionary?

  显示原文与译文双语对照的内容

我看到了几种在 C# 中迭代字典的不同方法。 有没有标准的方法?

时间:


foreach(KeyValuePair<string, string> entry in MyDic)
{
//do something with entry.Value or entry.Key
}

如果你试图在 C# 中使用通用字典,就像使用其他语言的关联数组一样:


foreach(var item in myDictionary)
{
 foo(item.Key);
 bar(item.Value);
}

或者,如果只需要遍历键集合,请使用


foreach(var item in myDictionary.Keys)
{
 foo(item);
}

最后,如果你只对值感兴趣:


foreach(var item in myDictionary.Values)
{
 foo(item);
}

( 注意 var 关键字是可选的C# 3.0和上特性,你也可以在这里使用键/值的确切类型)

在某些情况下,可能需要for-loop实现提供的计数器。 为此,LINQ提供了启用以下内容的ElementAt:


for (int index = 0; index <dictionary.Count; index++) {
 var item = dictionary.ElementAt(index);
 var itemKey = item.Key;
 var itemValue = item.Value;
}

取决于你是在键后面还是在值后面。。

从 MSDN 字典 <( <( TKey,TValue> ) )> 中获取类描述:


//When you use foreach to enumerate dictionary elements,
//the elements are retrieved as KeyValuePair objects.
 Console.WriteLine();
 foreach( KeyValuePair<string, string> kvp in openWith )
 {
 Console.WriteLine("Key = {0}, Value = {1}", 
 kvp.Key, kvp.Value);
 }

//To get the values alone, use the Values property.
 Dictionary<string, string>.ValueCollection valueColl =
 openWith.Values;

//The elements of the ValueCollection are strongly typed
//with the type that was specified for dictionary values.
 Console.WriteLine();
 foreach( string s in valueColl )
 {
 Console.WriteLine("Value = {0}", s);
 }

//To get the keys alone, use the Keys property.
 Dictionary<string, string>.KeyCollection keyColl =
 openWith.Keys;

//The elements of the KeyCollection are strongly typed
//with the type that was specified for dictionary keys.
 Console.WriteLine();
 foreach( string s in keyColl )
 {
 Console.WriteLine("Key = {0}", s);
 }

我想说的是,foreach是标准的方式,尽管它很明显取决于你正在寻找什么


foreach(var value in my_dictionary) {
. . .
}

这就是你要寻找的?

有很多选项。 我个人喜欢的是 KeyValuePair


Dictionary<string,object> myDictionary = new Dictionary<string,object>();
//Populate your dictionary here

Foreach (KeyValuePair<string,object> kvp in myDictionary)
{
//Do some interesting things;
}

你还可以使用关键字和值集合

你建议在下面进行迭代


Dictionary<string,object> myDictionary = new Dictionary<string,object>();
//Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary) {
//Do some interesting things;
}

仅供参考,如果值为 object,则 foreach 不起作用。

使用内置的支持迭代器模式,foreach关键字。

如果使用非通用字典,只需对不同的项使用KeyValuePair类型:


foreach(KeyValuePair item in myDictionary)
{
 DoStuffWith(item);
}

泛型版本几乎相同,除了定义KeyValuePair中的类型与字典相同:


foreach(KeyValuePair<Tkey, Tvalue> item in myDictionary)
{
 DoStuffWith(item);
}

我在MSDN上的DictionaryBase类的文档中找到了这里方法:


foreach (DictionaryEntry de in myDictionary)
{
//Do some stuff with de.Value or de.Key
}

这是我在一个继承自DictionaryBase的类中能够正常工作的唯一一个。

我欣赏这个问题已经有了很多的响应,但是我想给你一些研究。

数组的迭代相比,迭代字典可能比较慢。 在我的测试中迭代数组了 0.015 003秒而迭代字典( 具有相同数量的元素) 了 0.036 5073秒是三倍的时间! 虽然我看到了更大的差异。 为了进行比较,List 在 0.002 15043秒之间。

这就像比较苹果和桔子。 我的观点是,迭代字典是缓慢的。

字典是为查找而优化的,因此我已经创建了两种方法。 一个只是做一个 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.031 0062,密钥版本采用 0.220 5441. 加载所有的键并遍历所有查找显然要慢得多 !

对于最后一次测试,我执行了迭代十次,看看在这里使用键是否有任何好处( 这时我只是好奇):

下面是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.282秒 0564秒。 对密钥的迭代花费了 2.224秒的时间。

编辑添加:阅读其他的一些回答让我将会发生什么如果我使用字典而不是字典。 在本例中,数组花费了 0.012秒的时间,List 0.018 5037秒和字典 0.046 5093秒。 可以预料的是,数据类型对字典的慢得多。

我的结论

  • 避免在字典上迭代,如果可以,它们比在数组中使用相同数据的数组慢很多。
  • 如果你选择遍历字典,不要过于聪明,尽管你可以比使用标准的foreach方法更慢。
...