簡體   English   中英

使用linq表達式過濾帶有鍵列表的字典

[英]Use linq expression to filter a dictionary with a list of keys

我有一個字典,其中包含所有具有相應年齡的用戶。

Dictionary<string,int> AllUsers;

我有一個特定用戶列表。

List<String> Users;

我想過濾第一個字典AllUsers只有在SpecificUsers列表中有他們名字的用戶。

我已經用循環手動完成了一些事情,但是我想使用linq表達式,但我對它們並不是很熟悉。

在此先感謝您的幫助

它可能會奏效

var newdict = AllUsers.Where(x => Users.Contains(x.Key))
                                        .ToDictionary(val => val.Key, val => val.Value);

它將創建新的字典(因為linq用於查詢不更新)與字典中所有Users列表中的Users 您需要使用ToDictionary來實際制作字典。

編輯:正如@Rawling所說,過濾詞典而不是列表會更高效。 @Luaan答案中存在解決方案(我不會像有些人那樣復制)

您可以過濾Users

Users.Where(i => AllUsers.ContainsKey(i)).Select(i => new { User = i, Age = AllUsers[i] });

這樣做的主要好處是您使用索引的AllUsers進行過濾,因此您的總計算復雜度僅取決於用戶中的UsersDictionary.Contains是O(1)) - 天真的方法往往是Users * AllUsers

如果你想要輸出字典,就像用上面的.Select(...)替換它一樣簡單

.ToDictionary(i => i, i => AllUsers[i])

您可以使用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);

使用JOIN

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM