如何尽可能简单地使用 Linq 从字典中选择多个值

问题描述 投票:0回答:6

我需要根据键的子集从字典中选择多个值(放入列表中)。

我正在尝试使用 Linq 在一行代码中完成此操作,但到目前为止我发现的代码似乎相当长且笨拙。最短(最干净)的方法是什么?

这就是我现在所拥有的(键是字符串,keysToSelect 是要选择的键列表):

List<ValueType> selectedValues = dictionary1.Where(x => keysToSelect.Contains(x.Key))
                                            .ToDictionary<String, valueType>(x => x.Key,
                                                                             x => x.Value)
                                            .Values.ToList;

谢谢你。

c# linq dictionary
6个回答
77
投票

那么你可以从列表而不是字典开始:

var selectedValues = keysToSelect.Where(dictionary1.ContainsKey)
                     .Select(x => dictionary1[x])
                     .ToList();

如果保证所有键都在字典中,您可以省略第一个

Where

var selectedValues = keysToSelect.Select(x => dictionary1[x]).ToList();

请注意,此解决方案比迭代字典更快,特别是当要选择的键列表与字典的大小相比较小时,因为

Dictionary.ContainsKey
List.Contains
快得多。


9
投票

A

Dictionary<TKey,TValue>
IEnumerable<KeyValuePair<TKey,TValue>>
,因此您可以简单地
Select
Value
属性:

 List<ValueType> selectedValues = dictionary1
           .Where(x => keysToSelect.Contains(x.Key))
           .Select(x => x.Value)
           .ToList();

 var selectValues = (from keyValuePair in dictionary1
                     where keysToSelect.Contains(keyValuePair.Key)
                     select keyValuePair.Value).ToList()

5
投票

当不能保证键存在时,接受的答案不是很有效,因为它执行两次查找。

根据已接受的答案,我想出了这个扩展方法:

public static IEnumerable<TValue> GetMultiple<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, IEnumerable<TKey> keysToSelect)
{
    foreach (var key in keysToSelect)
        if (dictionary.TryGetValue(key, out TValue value))
            yield return value;
}

不完全是“单行”,但我发现它比链接四个 Linq 方法更具可读性。

用途:

var results = dictionary.GetMultiple(keysToSelect).ToList()

3
投票

如果您知道要选择的所有值都在字典中,则可以循环遍历键而不是循环遍历字典:

List<ValueType> selectedValues = keysToSelect.Select(k => dictionary1[k]).ToList();

1
投票

从查找的角度来看,接受的解决方案仍然不是最有效的选择,因为您仍然需要检查键是否在字典中两次:一次用于过滤键,一次用于查找对象。

此解决方案不存在该问题:

var selectedValues = keysToSelect
  .Select(_ => {
     var found = dict.TryGetValue(_, out TValue? result);
     return (found, result);
  })
  .Where(_ => _.found)
  .Select(_ => _.result!)
  .ToList();

0
投票

另一个不能重复工作的选项:

var dict = new Dictionary<int, string> {
    [1] = "one",
    [2] = "two",
    [3] = "three",
    [4] = "four"
};
var keys = new[] { 2, 4, 1 };

var result = dict
    .Join(keys, x => x.Key, k => k, (x, _) => x.Value)
    .ToArray();
© www.soinside.com 2019 - 2024. All rights reserved.