web-dev-qa-db-ja.com

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

私はC#辞書を持っています、Dictionary<Guid, MyObject>MyObjectのプロパティに基づいてフィルタリングする必要があること。

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

辞書はIEnumerable<KeyValuePair<Key, Value>>、使用できるのは Where

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

必要に応じて新しい辞書を再作成するには、 ToDictionary メソッドを使用します。

59
Lee

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

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

89
Mehrdad Afshari

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

var filtered = from kvp in myDictionary
               where !kvp.Value.BooleanProperty
               select kvp
7
Oded
    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);
    }
2
Ryan Williams

プロジェクトに次の拡張メソッドを追加しました。これにより、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);
0
aaaaaa

これは一般的な解決策であり、値のブールプロパティだけでなく機能します。

メソッド

注意:拡張メソッドは静的クラスに配置する必要があります。ソースファイルの先頭にある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);
0
Andi