题
我已经看到了一些不同的方式来迭代过一词典。是否有一个标准的方式?
解决方案
foreach(KeyValuePair<string, string> entry in myDictionary)
{
// 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循环实现提供的计数器。为此,LINQ提供 ElementAt
这使得以下内容成为可能:
for (int index = 0; index < dictionary.Count; index++) {
var item = dictionary.ElementAt(index);
var itemKey = item.Key;
var itemValue = item.Value;
}
取决于您是否在关键或值之后......
来自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);
}
通常,寻求"最好的办法"没有一个特定的上下文是像问 什么是最好的颜色?
一方面,有许多颜色和没有最好的颜色。它取决于需要和往往上的味道,也是。
另一方面,有许多方法可以迭代过一词典在C#而且也没有更好的方式。它取决于需要和往往上的味道,也是。
最简单的方法
foreach (var kvp in items)
{
// key is kvp.Key
doStuff(kvp.Value)
}
如果你只需要价值(可以称呼它 item
, ,更具可读性比 kvp.Value
).
foreach (var item in items.Values)
{
doStuff(item)
}
如果你需要一个具体的排列顺序
一般来说,初学者们惊讶的是有关以枚举的字典。
皇宫提供了一个简洁的语法,允许指定了(和许多其他的事情),例如:
foreach (var kvp in items.OrderBy(kvp => kvp.Key))
{
// key is kvp.Key
doStuff(kvp.Value)
}
再次,你可能只需要价值。皇宫还提供了一个简洁的解决方案:
- 迭代直接的价值(可以称呼它
item
, ,更具可读性比kvp.Value
) - 但按键
这里是:
foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
{
doStuff(item)
}
还有更多的实际使用的情况下,你可以从这些例子。如果你不需要一个特定的顺序,只是坚持"最直接的方式"(见上文)!
我会说foreach是标准方式,但显然取决于你在寻找什么
foreach(var kvp in my_dictionary) {
...
}
这就是你要找的东西吗?
您也可以在大字典上尝试使用多线程处理。
dictionary
.AsParallel()
.ForAll(pair =>
{
// Process pair.Key and pair.Value here
});
有很多选择。我个人最喜欢的是KeyValuePair
Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here
foreach (KeyValuePair<string,object> kvp in myDictionary)
{
// Do some interesting things
}
您还可以使用键和值集合
我很欣赏这个问题已经有很多的答复,但我要扔在一个小小的研究。
遍历一词典的可能是相当缓慢当与迭代的东西就像一个阵列。在我的测试的一个迭代过一阵了0.015003秒,而一个迭代过一词典(同的元素数)采取了0.0365073秒的2.4倍!虽然我已经看到更大的差异。为了比较一个列表中的某处之间在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方法。
C#7.0 介绍了解构主义者 如果您使用的是 .NET Core 2.0 + 应用程序,那么struct KeyValuePair<>
已经包含了Deconstruct()
。所以你可以这样做:
var dic = new Dictionary<int, string>() { { 1, "One" }, { 2, "Two" }, { 3, "Three" } };
foreach (var (key, value) in dic) {
Console.WriteLine($"Item [{key}] = {value}");
}
//Or
foreach (var (_, value) in dic) {
Console.WriteLine($"Item [NO_ID] = {value}");
}
//Or
foreach ((int key, string value) in dic) {
Console.WriteLine($"Item [{key}] = {value}");
}
您建议在下面进行迭代
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
不起作用。
使用.NET Framework 4.7
可以使用分解
var fruits = new Dictionary<string, int>();
...
foreach (var (fruit, number) in fruits)
{
Console.WriteLine(fruit + ": " + number);
}
要使此代码适用于较低的C#版本,请添加System.ValueTuple NuGet package
并写入某处
public static class MyExtensions
{
public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple,
out T1 key, out T2 value)
{
key = tuple.Key;
value = tuple.Value;
}
}
迭代字典的最简单形式:
foreach(var item in myDictionary)
{
Console.WriteLine(item.Key);
Console.WriteLine(item.Value);
}
使用 C#7 ,将此扩展方法添加到解决方案的任何项目中:
public static class IDictionaryExtensions
{
public static IEnumerable<(TKey, TValue)> Tuples<TKey, TValue>(
this IDictionary<TKey, TValue> dict)
{
foreach (KeyValuePair<TKey, TValue> kvp in dict)
yield return (kvp.Key, kvp.Value);
}
}
,点击 并使用这个简单的语法
foreach (var(id, value) in dict.Tuples())
{
// your code using 'id' and 'value'
}
,点击 或者这个,如果你愿意的话
foreach ((string id, object value) in dict.Tuples())
{
// your code using 'id' and 'value'
}
,点击 取代传统的
foreach (KeyValuePair<string, object> kvp in dict)
{
string id = kvp.Key;
object value = kvp.Value;
// your code using 'id' and 'value'
}
,点击
扩展方法将您的KeyValuePair
转换为强类型IDictionary<TKey, TValue>
,允许您使用这种新的舒适语法。
它将-just-所需的字典条目转换为tuple
,因此它不会将整个字典转换为tuples
,因此没有与此相关的性能问题。
与直接使用Key
相比,只需要很少的费用来调用创建Value
的扩展方法,如果您要分配<=>的属性<=>,这不应该是一个问题。无论如何<=>到新的循环变量。
在实践中,这种新语法非常适合大多数情况,除了低级超高性能方案,您仍然可以选择不在特定位置使用它。
检查一下: MSDN博客 - C#7中的新功能
有时,如果您只需要枚举值,请使用字典的值集合:
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上的DictionaryBase类的文档中找到了这个方法:
foreach (DictionaryEntry de in myDictionary)
{
//Do some stuff with de.Value or de.Key
}
这是我在从DictionaryBase继承的类中唯一能够正常运行的。
我将利用.NET 4.0+并为最初接受的答案提供更新的答案:
foreach(var entry in MyDic)
{
// do something with entry.Value or entry.Key
}
根据MSDN上的官方文档,迭代字典的标准方法是:
foreach (DictionaryEntry entry in myDictionary)
{
//Read entry.Key and entry.Value here
}
从C#7开始,您可以将对象解构为变量。我相信这是迭代字典的最好方法。
示例:强>
在KeyValuePair<TKey, TVal>
上创建一个解构它的扩展方法:
public static void Deconstruct<TKey, TVal>(this KeyValuePair<TKey, TVal> pair, out TKey, out TVal val)
{
key = pair.Key;
val = pair.Value;
}
以下列方式迭代任何Dictionary<TKey, TVal>
// Dictionary can be of any types, just using 'int' and 'string' as examples.
Dictionary<int, string> dict = new Dictionary<int, string>();
// Deconstructor gets called here.
foreach (var (key, value) in dict)
{
Console.WriteLine($"{key} : {value}");
}
如果说,您希望默认迭代值集合,我相信您可以实现IEnumerable <!> lt; <!> gt;,其中T是字典中值对象的类型,并且<! > QUOT;!这<> QUOT;是一本字典。
public new IEnumerator<T> GetEnumerator()
{
return this.Values.GetEnumerator();
}
var dictionary = new Dictionary<string, int>
{
{ "Key", 12 }
};
var aggregateObjectCollection = dictionary.Select(
entry => new AggregateObject(entry.Key, entry.Value));
只想添加我的2美分,因为大多数答案都与foreach-loop有关。 请看下面的代码:
Dictionary<String, Double> myProductPrices = new Dictionary<String, Double>();
//Add some entries to the dictionary
myProductPrices.ToList().ForEach(kvP =>
{
kvP.Value *= 1.15;
Console.Writeline(String.Format("Product '{0}' has a new price: {1} $", kvp.Key, kvP.Value));
});
Altought这增加了一个'.ToList()'的调用,可能会有一点性能提升(如此处所指出的 foreach vs someList.Foreach(){} ), 特别是在使用大字典并且并行运行时,没有选择/根本没有效果。
另外,请注意,您无法为foreach循环中的“Value”属性赋值。另一方面,您也可以操纵'Key',可能会在运行时遇到麻烦。
当你只想<!>“读取<!>”时;键和值,您也可以使用IEnumerable.Select()。
var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );
我写了一个扩展来循环字典。
public static class DictionaryExtension
{
public static void ForEach<T1, T2>(this Dictionary<T1, T2> dictionary, Action<T1, T2> action) {
foreach(KeyValuePair<T1, T2> keyValue in dictionary) {
action(keyValue.Key, keyValue.Value);
}
}
}
然后你可以打电话
myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y));
我知道这是一个非常古老的问题,但我创建了一些可能有用的扩展方法:
public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
{
foreach (KeyValuePair<T, U> p in d) { a(p); }
}
public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
{
foreach (T t in k) { a(t); }
}
public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
{
foreach (U u in v) { a(u); }
}
这样我就可以编写这样的代码:
myDictionary.ForEach(pair => Console.Write($"key: {pair.Key}, value: {pair.Value}"));
myDictionary.Keys.ForEach(key => Console.Write(key););
myDictionary.Values.ForEach(value => Console.Write(value););
<强>词典LT <!>; TKey,<!>#8194; TValue <!> gt; 它是c#中的通用集合类,它以键值格式存储数据.Key必须是唯一的,不能为null,而值可以复制并为null。字典中的每个项目都被视为KeyValuePair <!> lt; TKey,<!>#8194; TValue <!> gt;表示密钥及其价值的结构。因此我们应该采用元素类型KeyValuePair <!> lt; <!> TKEY的,#8194; <!> TValue GT;在元素的迭代过程中。以下是示例。
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");
foreach (KeyValuePair<int, string> item in dict)
{
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}
除了使用
之间进行讨论的排名最高的帖子foreach(KeyValuePair<string, string> entry in myDictionary)
{
// do something with entry.Value or entry.Key
}
或
foreach(var entry in myDictionary)
{
// do something with entry.Value or entry.Key
}
最完整的是以下因为你可以从初始化看到字典类型,kvp是KeyValuePair
var myDictionary = new Dictionary<string, string>(x);//fill dictionary with x
foreach(var kvp in myDictionary)//iterate over dictionary
{
// do something with kvp.Value or kvp.Key
}
字典是特殊列表,而列表中的每个值都有一个键 这也是一个变量。字典的一个很好的例子是电话簿。
Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 4154346543);
phonebook["Jessica"] = 4159484588;
请注意,在定义字典时,我们需要提供泛型 定义有两种类型 - 键的类型和值的类型。在这种情况下,键是一个字符串,而值是一个整数。
还有两种方法可以使用括号运算符或使用Add方法将单个值添加到字典中。
要检查字典中是否有某个键,我们可以使用ContainsKey方法:
Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;
if (phonebook.ContainsKey("Alex"))
{
Console.WriteLine("Alex's number is " + phonebook["Alex"]);
}
要从字典中删除项目,我们可以使用Remove方法。通过键从字典中删除项目非常快速且非常高效。使用其值从List中删除项目时,该过程缓慢且效率低,与字典删除功能不同。
Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;
phonebook.Remove("Jessica");
Console.WriteLine(phonebook.Count);