从 C# 通用字典中过滤出值

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

我有一个 C# 字典,

Dictionary<Guid, MyObject>
,我需要根据
MyObject
的属性进行过滤。

例如,我想从字典中删除

MyObject.BooleanProperty = false
的所有记录。实现这一目标的最佳方法是什么?

c# generics dictionary filtering
7个回答
148
投票

如果您不介意创建一本包含所需项目的新字典并扔掉旧字典,只需尝试:

dic = dic.Where(i => i.Value.BooleanProperty)
         .ToDictionary(i => i.Key, i => i.Value);

如果您无法创建新词典并且由于某种原因需要更改旧词典(例如当它被外部引用并且您无法更新所有引用时:

foreach (var item in dic.Where(item => !item.Value.BooleanProperty).ToList())
    dic.Remove(item.Key);

请注意,此处

ToList
是必需的,因为您正在修改基础集合。如果更改底层集合,则用于查询值的枚举器将无法使用,并将在下一个循环迭代中引发异常。
ToList
在更改字典之前缓存值。


94
投票

既然Dictionary实现了

IEnumerable<KeyValuePair<Key, Value>>
,你就可以使用
Where
:

var matches = dictionary.Where(kvp => !kvp.Value.BooleanProperty);

要重新创建新字典(如果需要),请使用

ToDictionary
方法。


10
投票

您可以简单地使用 Linq where 子句:

var filtered = from kvp in myDictionary
               where !kvp.Value.BooleanProperty
               select kvp

7
投票
    public static Dictionary<TKey, TValue> Where<TKey, TValue>(this Dictionary<TKey, TValue> instance, Func<KeyValuePair<TKey, TValue>, bool> predicate)
    {
        return Enumerable.Where(instance, predicate)
                         .ToDictionary(item => item.Key, item => item.Value);
    }

5
投票

这是一个通用解决方案,不仅适用于值的布尔属性。

方法

提醒:扩展方法必须放在静态类中。不要忘记源文件顶部的

using System.Linq;
语句。

    /// <summary>
    /// Creates a filtered copy of this dictionary, using the given predicate.
    /// </summary>
    public static Dictionary<K, V> Filter<K, V>(this Dictionary<K, V> dict,
            Predicate<KeyValuePair<K, V>> pred) {
        return dict.Where(it => pred(it)).ToDictionary(it => it.Key, it => it.Value);
    }

用法

示例:

    var onlyWithPositiveValues = allNumbers.Filter(it => it.Value > 0);

1
投票

希望它能满足您的需求。

Dictionary<string, string> d = new();
d.Add("Product", "SELECT * FROM PRODUCT");
d.Add("Order", "SELECT * FROM ORDER");
d.Add("Customer", "SELECT * FROM CUSTOMER");
    
var x = d.Where(kvp => kvp.Key == "Order")
   .ToDictionary(item => item.Key, item => item.Value)
   .FirstOrDefault();
if(x.Key != null)
{
   Console.WriteLine($"{x.Value}"); //this should return "SELECT * FROM ORDER";
}

0
投票

我为我的项目添加了以下扩展方法,它允许您过滤 IDictionary。

public static IDictionary<keyType, valType> KeepWhen<keyType, valType>(
    this IDictionary<keyType, valType> dict,
    Predicate<valType> predicate
) {
    return dict.Aggregate(
        new Dictionary<keyType, valType>(),
        (result, keyValPair) =>
        {
            var key = keyValPair.Key;
            var val = keyValPair.Value;

            if (predicate(val))
                result.Add(key, val);

            return result;
        }
    );
}

用途:

IDictionary<int, Person> oldPeople = personIdToPerson.KeepWhen(p => p.age > 29);
© www.soinside.com 2019 - 2024. All rights reserved.