选择一个枚举内从多个词典的值
问题描述:
如果我有字典的枚举选择一个枚举内从多个词典的值
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>
(但不是空)是很重要的。