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


74

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

Zum Beispiel möchte ich alle Datensätze aus dem Wörterbuch entfernen, wo MyObject.BooleanProperty = false. Was ist der beste Weg, um dies zu erreichen?

Antworten:


70

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

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

Verwenden Sie die ToDictionaryMethode, um ein neues Wörterbuch bei Bedarf neu zu erstellen .


1
Stellen Sie sicher, dass System.Linq using-Anweisung oben enthalten ist.
VivekDev

112

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

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 Referenzen aktualisieren können:

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

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


1
Ich habe mich gefragt, welche Parameter ich in der ToDictionary-Methode übergeben muss. Vielen Dank! +1
contactmatt

8

Sie können einfach die Linq where-Klausel verwenden:

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

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

0

Ich habe die 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;
        }
    );
}

Verwendung:

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

0

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);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.