Подтвердить что ты не робот

Фильтрация значений из общего словаря С#

У меня есть словарь С#, Dictionary<Guid, MyObject>, который мне нужно отфильтровать на основе свойства MyObject.

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

Вы можете просто использовать Linq, где пункт:

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

Ответ 4

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

Ответ 5

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

Ответ 6

метод

Напоминание: методы расширения должны быть размещены в статических классах.

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

использование

Пример:

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