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?

Fiona - myaccessible.website
quelle

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 .

Lee
quelle
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.

Mehrdad Afshari
quelle
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
Oded
quelle
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);
    }
Ryan Williams
quelle
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);
aaaaaa
quelle
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);
Und ich
quelle