LINQ:从Dictionary获取给定值列表的键,反之亦然

时间:2022-03-09 21:15:20

I have the following structure in my code Dictionary<TKeys, TValues> data;. I run some LINQ queries on both data types and often need to switch between Keys and Values. What is the best way to get the list of Keys for given Values and vice versa? Please, notice, that I usually have 'IEnumerable' and 'IEnumerable' as a result of my previous LINQ queries and would like to have something like IEnumerable<TKeys> Dictionary.GetAllKeys(IEnumerable<IValues> vals) and IEnumerable<TValues> Dictionary.GetAllValues(IEnumerable<IKeys> keys).

我的代码字典 data;中有以下结构。我在两种数据类型上运行一些LINQ查询,并且经常需要在键和值之间切换。获取给定值的键列表的最佳方法是什么,反之亦然?请注意,由于我之前的LINQ查询,我通常有'IEnumerable'和'IEnumerable',并希望有像IEnumerable Dictionary.GetAllKeys(IEnumerable vals)和IEnumerable Dictionary这样的东西。 .GetAllValues(IEnumerable 键)。 ,tvalues>

Maybe I need other data container for this task?

也许我需要其他数据容器来完成这项任务?

Regards, Alexander.

此致,亚历山大。

3 个解决方案

#1


29  

 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);

#2


10  

A Dictionary<,> really isn't great for finding keys by value. You could write a bidirectional dictionary, as I have done in this answer, but it wouldn't necessarily be the best approach.

字典<,>真的不适合按值查找键。你可以写一个双向字典,正如我在这个答案中所做的那样,但它不一定是最好的方法。

Of course you can use a dictionary as a sequence of key/value pairs, so you could have:

当然,您可以使用字典作为键/值对的序列,因此您可以:

var keysForValues = dictionary.Where(pair => values.Contains(pair.Value))
                              .Select(pair => pair.Key);

Just be aware this will be an O(n) operation, even if your "values" is a HashSet or something similar (with an efficient containment check).

请注意,这将是一个O(n)操作,即使您的“值”是HashSet或类似的东西(使用有效的包含检查)。

EDIT: If you don't really need a key/value relation - if it's more like they're just pairs - then using List<Tuple<Foo, Bar>> would make a certain amount of sense. The query ends up being the same, basically:

编辑:如果你真的不需要键/值关系 - 如果它更像是它们只是成对 - 那么使用List >会产生一定的意义。查询最终是相同的,基本上:

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));
}

#3


1  

The best approach is to perform your linq query on the collection of key-value pairs, then use a Select projection to select either the Keys or the Values at the end of your query. This way there is no need to perform a look-up at the end of your query.

最好的方法是对键值对的集合执行linq查询,然后使用Select投影选择查询末尾的Keys或Values。这样就无需在查询结束时执行查找。

For example:

例如:

  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);

#1


29  

 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);

#2


10  

A Dictionary<,> really isn't great for finding keys by value. You could write a bidirectional dictionary, as I have done in this answer, but it wouldn't necessarily be the best approach.

字典<,>真的不适合按值查找键。你可以写一个双向字典,正如我在这个答案中所做的那样,但它不一定是最好的方法。

Of course you can use a dictionary as a sequence of key/value pairs, so you could have:

当然,您可以使用字典作为键/值对的序列,因此您可以:

var keysForValues = dictionary.Where(pair => values.Contains(pair.Value))
                              .Select(pair => pair.Key);

Just be aware this will be an O(n) operation, even if your "values" is a HashSet or something similar (with an efficient containment check).

请注意,这将是一个O(n)操作,即使您的“值”是HashSet或类似的东西(使用有效的包含检查)。

EDIT: If you don't really need a key/value relation - if it's more like they're just pairs - then using List<Tuple<Foo, Bar>> would make a certain amount of sense. The query ends up being the same, basically:

编辑:如果你真的不需要键/值关系 - 如果它更像是它们只是成对 - 那么使用List >会产生一定的意义。查询最终是相同的,基本上:

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));
}

#3


1  

The best approach is to perform your linq query on the collection of key-value pairs, then use a Select projection to select either the Keys or the Values at the end of your query. This way there is no need to perform a look-up at the end of your query.

最好的方法是对键值对的集合执行linq查询,然后使用Select投影选择查询末尾的Keys或Values。这样就无需在查询结束时执行查找。

For example:

例如:

  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);