Фильтрация значений из универсального словаря C#


у меня есть словарь C#,Dictionary<Guid, MyObject> что я должен быть отфильтрован на основе свойства MyObject.

например, я хочу удалить все записи из словаря, где MyObject.BooleanProperty = false. Каков наилучший способ достичь этого?

4   51   2010-01-25 13:38:01

4 ответа:

Так как словарь реализует IEnumerable<KeyValuePair<Key, Value>>, вы можете просто использовать, где:

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

чтобы воссоздать новый словарь, если он вам нужен, используйте ToDictionary метод.

если вас не волнует создание нового словаря с нужными элементами и выбрасывание старого, просто попробуйте:

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 кэширует значения перед изменением словаря вообще.

вы можете просто использовать Linq где статья:

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

я добавил следующий метод расширения для моего проекта, который позволяет фильтровать 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);