选择一个枚举内从多个词典的值

问题描述:

如果我有字典的枚举选择一个枚举内从多个词典的值

IEnumerable<IDictionary<string, float>> enumeration 

我可以执行它LINQ查询,这样我可以由值从每个字典在枚举使用选择同样的钥匙?

我可以在一个循环做到这一点:

float f; 
foreach (var dictionary in enumeration) 
{ 
    if (dictionary.TryGetValue("some key", out f)) 
    { 
     Console.WriteLine(f); 
    } 
} 

(最终的计划是比较查询的性能诗句等效嵌套循环语句(本身无论从另一个查询或等效形成的枚举。环套))

您正在寻找这样的事情:

IEnumerable<float> vals = enumeration.Where(d => d.ContainsKey("some key")) 
            .Select(d => d["some key"]); 

该查询首先识别的辞典在SE quence包含指定键,然后为每个获取的对于给定的关键字的值。

这不如使用TryGetValue()的循环有效,因为它将执行两个字典访问 - 一个用于Where,另一个用于Select。或者,您可以创建一个返回值或从词典中默认的一种安全的方法,然后过滤掉默认值。这消除了重复的字典查找。

public static class DictionaryExt { 
    public static TValue FindOrDefault<TKey,TValue>( 
      this Dictionary<TKey,TValue> dic, 
      TKey key, TValue defaultValue) 
    { 
     TValue val; 
     return dic.TryGetValue(key, out val) ? val : defaultValue; 
    } 
} 

enumeration.Select(d => d.FindOrDefault("some key", float.NaN)) 
      .Where (f => f != float.NaN); 

LINQ在对象只是使用普通的.NET方法,所以你可能不会注意到任何性能差异 - LINQ可能是一点点更糟如果有什么开销一点点,因为,但我不会期望它是显而易见的。

也许是这样的:

var q = from d in enumeration 
     where d.ContainsKey("some key") 
     select d["some key"]; 

foreach (float f in q) 
{ 
    Console.WriteLine(f); 
} 

使用TryGetValue

float f = 0.0f; 
foreach (var dic in enumeration.Where(d => d.TryGetValue("some key", out f))) { 
    Console.WriteLine(f); 
} 

如果查询上不变集字典经常运行...只是捕获结果的查询实例。

//run once 
ILookup<string, float> myLookup = enumeration 
    .SelectMany(d => d) 
    .ToLookup(kvp => kvp.Key, kvp => kvp.Value); 

//run many times 
foreach(float f in myLookup["somekey"]) 
{ 
    Console.WriteLine(f); 
} 

需要注意的是,如果该键不存在于查找,你会得到一个空IEnumerable<float>(但不是空)是很重要的。