Как динамически удалить пару значений ключа из словаря, если ключ содержит некоторую подстроку?

1

У меня есть внешняя петля, итерация по массиву подстрок, которые должны быть сопоставлены в словаре. Во внутреннем цикле я хочу перебрать словарь и удалить запись, чей ключ содержит подстроку. Как это сделать, не получив "Collection is modified Exception"?

foreach (string outerKey in new string[] { "PAYERADDR_PAYERNAME", "RECADDR_RECNAME", "PAYERADDR_ADDR", "RECADDR_ADDR" })
{
    foreach (var item in _generalWorksheetData.Where(kvp => kvp.Value.Contains(outerKey)).ToList())
        {
            _generalWorksheetData.Remove(item.Key);
        }
}
  • 0
    Покажите свой код.
  • 0
    Вы пишете, что хотите удалить элементы, у которых есть ключ, содержащий некоторую строку, но в своем коде вы проверяете значения kvp.Value.Contains(outerKey) ;-) с вашим кодом, которым вы почти были. Это не работает, потому что вы выбираете элементы словаря здесь kvp ( KeyValuPair ), которые вы не должны изменять, если они являются частью цикла. Если бы вы взяли такие ключи, как .Select(kvp => kvp.Key).ToList() это сработало бы; -]
Теги:
dictionary

4 ответа

7
Лучший ответ

Вам нужна новая коллекция:

List<string> todelete = dictionary.Keys.Where(k => k.Contains("substring")).ToList();
todelete.ForEach(k => dictionary.Remove(k));

или с помощью foreach:

foreach (string key in todelete)
    dictionary.Remove(key);  // safe to delete since it a different collection

Если Dictionary.Keys реализовал IList а не только ICollection вы могли бы получить к нему доступ в обратном цикле для их удаления. Но поскольку индексатора нет, вы не можете.

  • 0
    хороший узнать что-то новое .. хотя бы об этом .. каждый хороший ...
  • 1
    @PranayRana: на самом деле List.ForEach - не причина, по которой он работает, а потому, что я создаю новый список с ToList . Как вы можете видеть теперь, вы можете использовать вместо него простой foreach -loop.
1

Просто обновите свой внутренний foreach следующим образом:

foreach (var item in _generalWorksheetData.Keys.Where(kvp => kvp.Contains(outerKey)).ToList())
   {
      _generalWorksheetData.Remove(item);
   }

Обратите внимание, что методы расширения LINQ ToList и ToArray позволяют изменять коллекции.

        List<string> sampleList = new List<string>();
        sampleList.Add("1");
        sampleList.Add("2");
        sampleList.Add("3");
        sampleList.Add("4");
        sampleList.Add("5");

        // Will not work
        foreach (string item in sampleList)
        {
            sampleList.Remove(item);
        }

        // Will work
        foreach (string item in sampleList.ToList())
        {
            sampleList.Remove(item);
        }
1

Найдите совпадение и удалите записи, как показано ниже.

var keysWithMatchingValues = dictionary.Where(d => d.Key.Contains("xyz"))
                               .Select(kvp => kvp.Key).ToList();

foreach(var key in keysWithMatchingValues)
    dictionary.Remove(key);
  • 0
    Это не компилируется, так как dic является KeyValuPair , но даже если вы используете Remove(dic.Key) это также приводит к изменению исключения Collection, которое OP хочет предотвратить. То же самое происходит, если вы используете dictionary.Keys.Where(...) Ключи. dictionary.Keys.Where(...) вместо этого.
  • 0
    @TimSchmelter - я нашел проблему и решил ее, взяв значения в списке ...
1

AFAIK, вы не можете. Однако вы можете сохранить эти пары в списке и удалить их в отдельном цикле с первого.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню