【问题标题】:How to find an element in Dictionary with LINQ如何使用 LINQ 在字典中查找元素
【发布时间】:2019-08-20 13:55:20
【问题描述】:

我有一个代码:

var status = ...
var StatusMapping = new Dictionary<AnotherStatus, IList<Status>>
{
    {
        AnotherStatus,
        new List<Status>
        {
            Status1,
            Status2
        }
    }
}

foreach (var keyValuePair in StatusMapping)
{
    if (keyValuePair.Value.Contains(status))
    {
        return keyValuePair.Key;
    }
}

throw Exception(); 

我是 C# 新手,从 Java 切换过来的。在java中很容易做到这一点:

return StatusMapping
    .entrySet()
    .stream()
    .filter(e -> e.getValue().contains(status))
    .map(Map.Entry::getKey)
    .findFirst()
    .orElseThrow(() -> new Exception());

有没有办法用 LINQ 做到这一点?

【问题讨论】:

标签: c# linq


【解决方案1】:

首先,如果您经常这样做,您可能需要考虑另一种数据结构。字典并不是真正用于频繁的“基于值的某些方面的查找”。

哦,在 C# 中它更简单:)

var key = StatusMapping.First(x => x.Value.Contains(status)).Key;

First() 将在没有任何匹配项时抛出异常。

如果您想以默认值结束,您可以使用:

var key = StatusMapping.FirstOrDefault(x => x.Value.Contains(status)).Key;

这将导致key 成为AnotherStatus 的默认值(或任何密钥类型)。

请注意,这完全只能像这样工作,因为KeyValuePair&lt;,&gt; 是一个值类型,所以默认值是非空的,带有一个默认键。如果您有一系列 reference 类型,则需要类似:

var property = sequence.FirstOrDefault(whatever)?.Property;

...其中?. 是空条件运算符。

【讨论】:

  • KeyValuePair 对我来说是一个新的值类型。如果var key = StatusMapping.FirstOrDefault(x =&gt; x.Value.Contains(status)).Key; 被调用时的状态不在字典中任何键的值列表中,则键变量将具有状态枚举的默认值。这种行为是故意的吗? (应该会出现异常)
  • @Matt.G:无论密钥类型是什么,它都会有默认值,而不是Status。是的,这是故意的——我已将其澄清为“如果您想以默认值结束”。但是First()抛出异常。所以你可以让它以你想要的方式运行。
  • 感谢您的解释。我想我更感兴趣的是找出设计决策背后的原因,使 KeyValuePair 成为结构(值类型),而不是类(引用类型)(参考链接就足够了)。另外,这是我的错字,我的意思是 AnotherStatus 的默认值(这是关键)。
  • @Matt.G:我怀疑这主要是为了提高效率。您通常不要在遍历字典时(或在存储元素时永久地)为每个元素创建一个完整的额外对象。
  • @KirillBazarov:我们对用例了解得不够多。例如,您可能希望保留两本字典,单向一本。
猜你喜欢
  • 1970-01-01
  • 2013-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多