LINQ过滤类型列表中的字典值

时间:2011-07-14 16:44:50

标签: c# linq

认为这是一个非常基本的问题,但这是我的第一个LINQ查询,我完全陷入困境:

我有一个包含字符串键和列表值的字典(请参阅下面的定义),并希望提取已通过字典键选择列表的特定类型列表的元素。

IDictionary<string, IList<MyBaseType>> dataItemMap;

MySubType扩展MyBaseType。

我的狡猾疑问是:

string identCode = "foo";

IEnumerable<MySubType> query = 
    from entry in dataItemMap
    where entry.Key == identCode
    select entry.Value.OfType<MySubType>();

错误消息(来自LinqPad):

Cannot implicitly convert type
'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<MySubType>>'
to 'System.Collections.Generic.IEnumerable<MySubType>'.
An explicit conversion exists (are you missing a cast?)

问题显然在条目中.Value.OfType&lt;&gt;但是如何指定列表元素?我正在寻找像entry.Value.Items.OfType&lt;&gt;这样的东西。 ?

感谢。

2 个答案:

答案 0 :(得分:8)

我想你想要这样的东西:

IEnumberable<MySubType> query = dataItemMap[identCode].OfType<MySubType>();

这将获得具有给定键的列表,然后过滤它以仅返回MySubType元素。

答案 1 :(得分:3)

编辑:我一直在关注为什么现有的解决方案不起作用(以及“我有一个每个元素的值列表,我想要扁平化”的一般问题)而不是退后。正如Andy的回答所示,你几乎可以肯定地使用它是一个字典的事实 - 将它从O(n)操作转换为O(1):)

两个警告:

  • 您当前的代码将始终执行与identCode和字典键的序数,文化不敏感的比较;使用字典查找将使用它构造的任何比较器。
  • 如果在字典中找不到identCode,您当前的代码将返回空序列;字典索引器会抛出异常。如果您想避免这种情况,可以使用TryGetValue

请注意,如果您知道上次挑选的所有元素都是实际的正确类型,那么使用Cast可能比{{1}更好}:

OfType

当两者都有效时,我通常更喜欢var query = dataItemMap[identCode].Cast<MySubType>(); Cast,因为这意味着如果我对序列中数据的假设不正确,我会发现它有异常,而不是默默地丢失数据

请注意,OfType也会返回Cast元素,而null则不会。


不,问题不在于使用OfType - 这是因为你最终得到了一系列序列,但是你试图将它分配给一个序列。

更改返回类型,或使用其他OfType<>子句展平结果:

from

我很想直接使用扩展方法:

IEnumerable<MySubType> query =  from entry in dataItemMap
                                where entry.Key == identCode
                                from value in entry.Value.OfType<MySubType>()
                                select value;