如何遍历字典?

问:

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

答1:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

foreach(KeyValuePair entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

这很好,但是是否有任何简洁的语法可以将键和值从 KeyValuePair 解压缩到它们自己的变量中?例如,在 Python 中,如果我知道我的键是人名和值地址,我可能会写 for (name, address) in myDictionary.items()

@user2428107 您可以在 c# 中使用解构来完成此操作。 foreach (var (key, value) in myDictionary)

答2:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

如果您尝试在 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 及更高版本功能,您也可以在此处使用您的键/值的确切类型)

我很欣赏这个答案指出您可以明确地迭代键或值。

在我看来,var 应该谨慎使用。特别是在这里,它不是建设性的:类型 KeyValuePair 可能与问题相关。

var 有一个独特的目的,我不认为它是“句法”糖。有目的地使用它是一种适当的方法。

在 foreach 语句中使用 var 是危险的,因为有时编译器将“var”替换为“object”而不是使用正确的类型。

@JamesWierzba 我会说影响可读性的是缺少一个好的变量名(因为它是一个演示示例)。在实际代码中,如果它是 foreach (var vehicle in line.Values) { start(vehicle); },它将是可读的。

答3:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

在某些情况下,您可能需要一个可能由 for 循环实现提供的计数器。为此,LINQ 提供了 ElementAt,它启用了以下功能:

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

要使用 '.ElementAt' 方法,请记住: using System.Linq;这不包括在 fx 中。自动生成的测试类。

如果您要修改与键关联的值,这是要走的路。否则在修改和使用 foreach() 时会抛出异常。

ElementAt 不是 O(n) 操作吗?

这个答案完全不值得这么多赞成。字典没有隐式顺序,因此在此上下文中使用 .ElementAt 可能会导致细微的错误。更严重的是上面阿图罗的观点。您将迭代字典 dictionary.Count + 1 次,导致 O(n^2) 复杂度的操作应该仅为 O(n)。如果您确实需要索引(如果需要,您可能首先使用了错误的集合类型),您应该迭代 dictionary.Select( (kvp, idx) => new {Index = idx, kvp.Key, kvp.Value}) 而不是在循环内使用 .ElementAt。

ElementAt - o(n) 操作!严重地?这是你不应该怎么做的例子。这么多赞?

答4:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

取决于您是追求键还是值…

来自 MSDN Dictionary(TKey, TValue) 类描述:

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

// To get the values alone, use the Values property.
Dictionary.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.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);
}

答5:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

一般来说,在没有特定上下文的情况下询问“最好的方式”就像问什么是最好的颜色?

一方面,有很多颜色,没有最好的颜色。这取决于需要,通常也取决于口味。

另一方面,有很多方法可以在 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)
}

您可以从这些示例中做更多的实际用例。如果您不需要特定的顺序,只需坚持“最直接的方式”(见上文)!

最后一个应该是 .Values 而不是 select 子句。

@Mafii 你确定吗? OrderBy 返回的值不是 KeyValuePair 类型,它们没有 Value 字段。我在这里看到的确切类型是 IOrderedEnumerable>。也许你的意思是别的?你能写一个完整的行来说明你的意思(并测试它)吗?

我认为这个答案包含我的意思:stackoverflow.com/a/141105/5962841 但如果我混淆了某些东西,请纠正我

@Mafii 重新阅读我的整个答案,代码部分之间的解释说明了上下文。您提到的答案就像我的答案中的第二个代码部分(不需要顺序)。我刚刚按照您的建议写了items.Value。在您评论的第四部分的情况下,Select() 是一种使 foreach 直接枚举字典中的值而不是键值对的方法。如果在这种情况下您不喜欢 Select(),您可能更喜欢第三个代码部分。第四部分的重点是表明可以使用 LINQ 对集合进行预处理。

如果您执行 .Keys.Orderby(),您将迭代一个键列表。如果这就是你所需要的,那很好。如果您需要值,那么在循环中,您必须在每个键上查询字典以获取值。在许多情况下,它不会产生实际的影响。在高性能场景中,它会。就像我在答案开头所写的那样:“有很多方法(......)并且没有最好的方法。这取决于需要,而且通常也取决于品味。”

答6:

huntsbot.com – 高效赚钱,自由工作

C# 7.0 introduced Deconstructors,如果您使用的是 .NET Core 2.0+ 应用程序,则结构 KeyValuePair<> 已经为您包含了一个 Deconstruct()。所以你可以这样做:

var dic = new Dictionary() { { 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}");
}

https://i.stack.imgur.com/OdW3m.png

如果您使用的 .NET Framework,至少 4.7.2 没有 KeyValuePair 上的解构,试试这个:foreach (var (key, value) in dic.Select(x => (x.Key, x.Value)))

答7:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

我会说 foreach 是标准方式,尽管它显然取决于您要查找的内容

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

那是你要找的吗?

答8:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

您也可以在用于多线程处理的大字典上尝试此操作。

dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});

@WiiMaxx 更重要的是,如果这些项目不相互依赖

答9:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

我很欣赏这个问题已经有很多回应,但我想进行一些研究。

与迭代数组之类的东西相比,迭代字典可能会相当慢。在我的测试中,对数组的迭代需要 0.015003 秒,而对字典(具有相同数量的元素)的迭代需要 0.0365073 秒,是 2.4 倍!虽然我看到了更大的差异。为了比较,列表介于 0.00215043 秒之间。

然而,这就像比较苹果和橘子。我的观点是迭代字典很慢。

字典针对查找进行了优化,因此考虑到这一点,我创建了两种方法。一个简单地做一个 foreach,另一个迭代键然后查找。

public static string Normal(Dictionary dictionary)
{
    string value;
    int count = 0;
    foreach (var kvp in dictionary)
    {
        value = kvp.Value;
        count++;
    }

    return "Normal";
}

这个加载键并对其进行迭代(我也尝试将键拉入字符串 [] 但差异可以忽略不计。

public static string Keys(Dictionary 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 dictionary, Func 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 秒。

编辑添加:阅读其他一些答案让我质疑如果我使用 Dictionary 而不是 Dictionary 会发生什么。在这个例子中,数组耗时 0.0120024 秒,列表耗时 0.0185037 秒,字典耗时 0.0465093 秒。可以合理地预期数据类型会影响字典的速度。

我的结论是什么?

如果可以,请避免迭代字典,它们比迭代具有相同数据的数组要慢得多。

如果您确实选择遍历字典,请不要太聪明,尽管速度较慢,但您可能会比使用标准 foreach 方法做得更糟。

您应该使用 StopWatch 而不是 DateTime 之类的东西进行测量:hanselman.com/blog/…

你能否描述一下你的测试场景,你的字典中有多少项目,你多久运行一次你的场景来计算平均时间,......

有趣的是,根据字典中的数据,您会得到不同的结果。在迭代字典时,枚举器函数必须跳过字典中的许多空槽,这导致它比迭代数组慢。如果 Dictionary 已满,则要跳过的空槽将比它为半空时少。

答10:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

正如在此 answer 中已经指出的那样,KeyValuePair<TKey, TValue> 实现了从 .NET Core 2.0、.NET Standard 2.1 和 .NET Framework 5.0(预览版)开始的 Deconstruct 方法。

有了这个,就可以以与 KeyValuePair 无关的方式遍历字典:

var dictionary = new Dictionary();

// ...

foreach (var (key, value) in dictionary)
{
    // ...
}

答11:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

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

Dictionary myDictionary = new Dictionary();
// Populate your dictionary here

foreach (KeyValuePair kvp in myDictionary)
{
     // Do some interesting things
}

您还可以使用键和值集合

赞成这个..并欣赏不使用“var”。我讨厌其中带有“var”的代码示例。除非它是“var emp = new Employee()”...人们不知道/很少知道 var 是什么。谢谢。

@granadaCoder 如果没有人知道 var 是什么,那么您的命名不正确

原文链接:https://www.huntsbot.com/qa/7QZ4/how-to-iterate-over-a-dictionary?lang=zh_CN&from=csdn

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Python遍历字典的几种方法: 1.使用for循环遍历字典的键值对 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} for name, language in favorite_languages.items(): print(name + "'s favorite language is " + language) ``` 2.使用for循环遍历字典的键 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} for name in favorite_languages.keys(): print(name) ``` 3.使用for循环遍历字典的值 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} for language in favorite_languages.values(): print(language) ``` 4.使用列表推导式遍历字典的键值对 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} print([(name, language) for name, language in favorite_languages.items()]) ``` 5.使用列表推导式遍历字典的键 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} print([name for name in favorite_languages.keys()]) ``` 6.使用列表推导式遍历字典的值 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} print([language for language in favorite_languages.values()]) ``` 7.使用字典方法items()遍历字典的键值对 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} for item in favorite_languages.items(): print(item) ``` 8.使用字典方法keys()遍历字典的键 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} for key in favorite_languages.keys(): print(key) ``` 9.使用字典方法values()遍历字典的值 ```python favorite_languages = {'Tom': 'python', 'Jerry': 'c', 'Mickey': 'ruby'} for value in favorite_languages.values(): print(value) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值