我看到了一些不同的方法来迭代C#中的字典。有标准的方法吗?
当前回答
我想说foreach是标准的方法,尽管这显然取决于你想要什么
foreach(var kvp in my_dictionary) {
...
}
这就是你要找的吗?
其他回答
如果您希望在默认情况下迭代值集合,我相信您可以实现IEnumerable<>,其中T是字典中值对象的类型,“this”是字典。
public new IEnumerator<T> GetEnumerator()
{
return this.Values.GetEnumerator();
}
我在MSDN上DictionaryBase类的文档中找到了此方法:
foreach (DictionaryEntry de in myDictionary)
{
//Do some stuff with de.Value or de.Key
}
这是我唯一能够在从DictionaryBase继承的类中正确运行的一个。
我很感激这个问题已经得到了很多回应,但我想做一点研究。
与在数组等对象上迭代相比,在字典上迭代可能会相当慢。在我的测试中,对数组的迭代耗时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方法做得更糟。
根据MSDN上的官方文档,迭代字典的标准方法是:
foreach (DictionaryEntry entry in myDictionary)
{
//Read entry.Key and entry.Value here
}
一般来说,在没有特定上下文的情况下要求“最佳方式”就像要求什么是最好的颜色?
一方面,有很多颜色,没有最好的颜色。这取决于需求,也常常取决于口味。
另一方面,有很多方法可以在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)
}
从这些示例中可以看到更多真实世界的用例。如果您不需要特定的订单,只需坚持“最直接的方式”(见上文)!
推荐文章
- 如何在c#中获得正确的时间戳
- Linq选择列表中存在的对象(A,B,C)
- c# .NET中的App.config是什么?如何使用它?
- 从csv文件创建字典?
- c#:如何获得一个字符串的第一个字符?
- String类中的什么方法只返回前N个字符?
- 更好的方法将对象转换为int类型
- 我可以将c#字符串值转换为转义字符串文字吗?
- 在c#中转换char到int
- c#中朋友的对等物是什么?
- 关键字使用virtual+override vs. new
- 在ASP中选择Tag Helper。NET Core MVC
- 如何在没有任何错误或警告的情况下找到构建失败的原因
- 跨线程操作无效:控件“textBox1”从创建它的线程以外的线程访问
- 否ConcurrentList<T>在。net 4.0?