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
.
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.
Sie können einfach die Klausel Linq where verwenden:
var filtered = from kvp in myDictionary
where !kvp.Value.BooleanProperty
select kvp
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);
}
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);
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);