使用linq表达式筛选带有键列表的字典
本文关键字:列表 字典 linq 表达式 筛选 使用 | 更新日期: 2023-09-27 18:11:06
我有一个包含所有用户及其相应年龄的字典。
Dictionary<string,int> AllUsers;
我有一个特定用户的列表。
List<String> Users;
我想过滤第一个字典AllUsers
,只包含名字在SpecificUsers
列表中的用户。
我已经用循环手工做了一些事情,但我想使用linq表达式,但我对它们不是很熟悉。
提前感谢您的帮助
可以过滤Users
:
Users.Where(i => AllUsers.ContainsKey(i)).Select(i => new { User = i, Age = AllUsers[i] });
这样做的主要好处是您使用索引的AllUsers
来进行过滤,因此您的总计算复杂性仅取决于Users
中的用户数量(Dictionary.Contains
为0(1))—naïve方法倾向于Users * AllUsers
。
如果您希望输出一个字典,只需将上面的.Select(...)
替换为
.ToDictionary(i => i, i => AllUsers[i])
可能行得通
var newdict = AllUsers.Where(x => Users.Contains(x.Key))
.ToDictionary(val => val.Key, val => val.Value);
它将创建一个包含Users
列表中所有用户的新字典(因为linq用于查询而不是更新)。您需要使用ToDictionary
来实际使其成为字典。
编辑:正如@Rawling所说,在字典上过滤比在列表上过滤更高效。实现这一目标的解决方案存在于@Luaan答案中(我不会像有些人那样复制它)
您可以使用join()方法实际连接两个集合。它允许我们用一行linq得到你需要的东西。
var allUsers = new Dictionary<string, int>();
allUsers.Add("Bob", 10);
allUsers.Add("Tom", 20);
allUsers.Add("Ann", 30);
var users = new List<string>();
users.Add("Bob");
users.Add("Tom");
users.Add("Jack");
var result = allUsers.Join(users, o => o.Key, i => i, (o, i) => o);
foreach(var r in result)
{
Console.WriteLine(r.Key + " " + r.Value);
}
它将在控制台中输出以下内容:
Bob 10
Tom 20
结果集合
有多种方法可以做到这一点
可以使用where
关键字
var result= yourDictionary.Where(p=> yourList.Contains(p.Key))
.ToDictionary(p=> p.Key, p=> p.Value);
但是如果你有很多条目,最好使用HashSet
var strings = new HashSet<string>(yourList);
var result= yourDictionary.Where(p=> strings.Contains(p.Key))
.ToDictionary(p=> p.Key, p=> p.Value);
使用<<p> strong>与 var query =
from kvp in yourDictionary
join s in yourList on kvp.Key equals s
select new { kvp.Key, kvp.Value };
借助以下有用的函数
public static class Extensions
{
public static KeyValuePair<TKey,TValue>? Find<TKey, TValue>(this IDictionary<TKey, TValue> source, TKey key)
{
TValue value;
return source.TryGetValue(key, out value) ? new KeyValuePair<TKey, TValue>(key, value) : (KeyValuePair<TKey, TValue>?)null;
}
}
这是IMO的最佳解决方案(对每个键使用单个查找并且不引入闭包):
var filteredUsers = Users.Select(AllUsers.Find)
.Where(item => item.HasValue)
.ToDictionary(item => item.Value.Key, item => item.Value.Value);