53


9

C#汎用ディクショナリから値を除外する

MyObject`のプロパティに基づいてフィルタリングする必要があるC#辞書 Dictionary`があります。

たとえば、 `MyObject.BooleanProperty = false`の辞書からすべてのレコードを削除したいです。 これを達成する最良の方法は何ですか?

5 Answer


81


目的の項目で新しい辞書を作成し、古いものを捨てることを気にしない場合は、単に試してください:

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`は辞書を変更する前に値をキャッシュします。


52


辞書は IEnumerable>`を実装しているため、https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.where?view = netframework-4.7.2 [`Where]を使用できます。 :

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

必要に応じて新しい辞書を再作成するには、https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.todictionary?view = netframework-4.7.2 [ToDictionary]を使用します方法。


7


Linq where句を使用するだけです。

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


1


    public static Dictionary Where(this Dictionary instance, Func, bool> predicate)
    {
        return Enumerable.Where(instance, predicate)
                         .ToDictionary(item => item.Key, item => item.Value);
    }


0


プロジェクトに次の拡張メソッドを追加しました。これにより、IDictionaryをフィルタリングできます。

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

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

            return result;
        }
    );
}

使用法:

IDictionary oldPeople = personIdToPerson.KeepWhen(p => p.age > 29);