我的代码Dictionary<TKeys, TValues> data;
中有以下结构。
我对两种数据类型都运行了一些LINQ查询,并且经常需要在Keys
和Values
之间切换。
获取给定值的键列表的最佳方法是什么,反之亦然?
请注意,由于我以前的LINQ查询,我通常会有'IEnumerable'和'IEnumerable',并希望有类似IEnumerable<TKeys> Dictionary.GetAllKeys(IEnumerable<IValues> vals)
和IEnumerable<TValues> Dictionary.GetAllValues(IEnumerable<IKeys> keys)
的内容。
也许我需要其他数据容器来完成这项任务?
此致 亚历山大。
答案 0 :(得分:31)
var values = dictionary.Where(x => someKeys.Contains(x.Key)).Select(x => x.Value);
var keys = dictionary.Where(x => someValues.Contains(x.Value)).Select(x => x.Key);
答案 1 :(得分:11)
Dictionary<,>
对于按值查找密钥真的不太好。您可以编写双向字典,I have done in this answer,但它不会必然是最好的方法。
当然你可以使用字典作为一系列键/值对,所以你可以拥有:
var keysForValues = dictionary.Where(pair => values.Contains(pair.Value))
.Select(pair => pair.Key);
请注意,这将是一个O(n)操作,即使您的“值”是HashSet
或类似的东西(使用有效的收容检查)。
编辑:如果你不真的需要一个键/值关系 - 如果它更像是他们只是配对 - 那么使用List<Tuple<Foo, Bar>>
会产生一定的意义。查询最终基本相同:
public IEnumerable<T1> GetAllFirst<T1, T2>(IEnumerable<Tuple<T1, T2>> source,
IEnumerable<T2> seconds)
{
HashSet<T2> secondsSet = new HashSet<T2>(seconds);
return source.Where(pair => secondsSet.Contains(pair.Item2));
}
public IEnumerable<T2> GetAllSecond<T1, T2>(IEnumerable<Tuple<T1, T2>> source,
IEnumerable<T1> firsts)
{
HashSet<T1> firstsSet = new HashSet<T1>(firsts);
return source.Where(pair => firstsSet.Contains(pair.Item1));
}
答案 2 :(得分:1)
最好的方法是对键值对的集合执行linq查询,然后使用“选择”投影选择查询末尾的“键”或“值”。这样就无需在查询结束时执行查找。
例如:
Dictionary<string, string> data = new Dictionary<string, string>();
// select all values for keys that contain the letter 'A'
var values = data.Where(pair => pair.Key.Contains("A"))
.Select(pair => pair.Value);