it-swarm.com.de

Ausfiltern von Werten aus einem generischen C # -Wörterbuch

Ich habe ein C # Wörterbuch, Dictionary<Guid, MyObject>, das ich basierend auf einer Eigenschaft von MyObject filtern muss.

Ich möchte zum Beispiel alle Datensätze aus dem Wörterbuch entfernen, in denen MyObject.BooleanProperty = false. Was ist der beste Weg dies zu erreichen?

Da Dictionary IEnumerable<KeyValuePair<Key, Value>> implementiert, können Sie einfach Where verwenden:

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

Um ein neues Wörterbuch bei Bedarf neu zu erstellen, verwenden Sie die Methode ToDictionary .

52
Lee

Wenn Sie kein neues Wörterbuch mit den gewünschten Elementen erstellen und das alte wegwerfen möchten, versuchen Sie einfach Folgendes:

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

Wenn Sie kein neues Wörterbuch erstellen können und das alte aus irgendeinem Grund ändern müssen (z. B. wenn es extern referenziert wird und Sie nicht alle Verweise aktualisieren können:

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

Beachten Sie, dass hier ToList erforderlich ist, da Sie die zugrunde liegende Sammlung ändern. Wenn Sie die zugrunde liegende Auflistung ändern, ist der Enumerator, der die Werte abfragt, unbrauchbar und löst bei der nächsten Schleifeniteration eine Ausnahme aus. ToList speichert die Werte zwischen, bevor das Wörterbuch überhaupt geändert wird.

81
Mehrdad Afshari

Sie können einfach die Klausel Linq where verwenden:

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);
    }
1
Ryan Williams

Ich habe folgende Erweiterungsmethode für mein Projekt hinzugefügt, mit der Sie ein IDictionary filtern können.

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

Verwendungszweck:

IDictionary<int, Person> oldPeople = personIdToPerson.KeepWhen(p => p.age > 29);
0
aaaaaa

Hier ist eine allgemeine Lösung, die nicht nur für boolesche Eigenschaften der Werte funktioniert.

Methode

Erinnerung: Erweiterungsmethoden müssen in statischen Klassen platziert werden. Vergessen Sie nicht die using System.Linq; -Anweisung oben in der Quelldatei.

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

Verwendung

Beispiel:

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