我看到了一些不同的方法来迭代C#中的字典。有标准的方法吗?
当前回答
最好的答案当然是:想一想,如果你计划迭代,你是否可以使用比字典更合适的数据结构-正如Vikas Gupta在问题讨论开始时已经提到的那样。但作为整个主题的讨论仍然缺乏令人惊讶的好选择。一个是:
SortedList<string, string> x = new SortedList<string, string>();
x.Add("key1", "value1");
x.Add("key2", "value2");
x["key3"] = "value3";
foreach( KeyValuePair<string, string> kvPair in x )
Console.WriteLine($"{kvPair.Key}, {kvPair.Value}");
为什么它会被认为是在字典上迭代的代码味道(例如,通过foreach(KeyValuePair<,>)?
清洁编码的基本原则:“表达意图!”罗伯特·C·马丁在《干净的代码》中写道:“选择能揭示意图的名字”。很明显,单是命名太弱了。“表达(揭示)每一个编码决策的意图”更好地表达了这一点。
一个相关的原则是“最小惊讶原则”。
为什么这与遍历字典有关?选择字典表达了选择数据结构的意图,该数据结构主要用于按关键字查找数据。如今,.NET中有太多的替代方案,如果您想遍历键/值对,可以选择其他选项。
此外:如果您迭代某个项目,您必须揭示项目的排序方式和预期排序方式!尽管Dictionary的已知实现按照添加项的顺序对密钥集合进行排序-AFAIK,Dictionary没有关于订购的可靠规范(有吗?)。
但替代方案是什么?
TLDR:SortedList:如果您的集合没有变得太大,一个简单的解决方案是使用SortedList<,>,它还为键/值对提供了完整的索引。
微软有一篇关于提及和解释试衣系列的长文:键控集合
提到最重要的:KeyedCollection<,>和SortedDictionary<,>。SortedDictionary<,>比SortedList快一点,仅当它变大时才插入,但缺少索引,并且仅当插入的O(log n)优先于其他操作时才需要。如果您真的需要O(1)来插入并接受较慢的迭代,则必须使用简单的Dictionary<,>。显然,对于每种可能的操作,没有最快的数据结构。。
此外,还有ImmutableSortedDictionary<,>。
如果一个数据结构不是您所需要的,那么从Dictionary<,>或甚至从新的ConcurrentDictionary>派生,并添加显式迭代/排序函数!
其他回答
如果您试图在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及以上版本的特性,您也可以在此处使用键/值的确切类型)
迭代字典的最简单形式:
foreach(var item in myDictionary)
{
Console.WriteLine(item.Key);
Console.WriteLine(item.Value);
}
有很多选择。我个人最喜欢的是KeyValuePair
Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here
foreach (KeyValuePair<string,object> kvp in myDictionary)
{
// Do some interesting things
}
您也可以使用键和值集合
取决于你是在寻找关键点还是值。。。
来自MSDN Dictionary(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);
}
您也可以在用于多线程处理的大型字典上尝试此操作。
dictionary
.AsParallel()
.ForAll(pair =>
{
// Process pair.Key and pair.Value here
});
推荐文章
- dynamic (c# 4)和var之间的区别是什么?
- Visual Studio: ContextSwitchDeadlock
- 返回文件在ASP。Net Core Web API
- 自定义HttpClient请求头
- 如果我使用OWIN Startup.cs类并将所有配置移动到那里,我是否需要一个Global.asax.cs文件?
- VS2013外部构建错误"error MSB4019: The imported project <path> was not found"
- 从另一个列表id中排序一个列表
- 等待一个无效的异步方法
- 无法加载文件或程序集…参数不正确
- c#中枚举中的方法
- 如何从字符串中删除新的行字符?
- 如何设置一个默认值与Html.TextBoxFor?
- 检查属性是否有属性
- 格式化XML字符串以打印友好的XML字符串
- 返回内容与IHttpActionResult非ok响应