Самый эффективный способ удалить элементы из списка, не сталкиваясь с измененным исключением коллекции? - PullRequest
2 голосов
/ 07 июля 2011

У меня есть 2 списка:

ListA { 'A', 'B', 'C' } //ListA is DictA.Keys
ListB { 'B', 'X', 'Y' } //ListB is DictB.Keys

Если я сделаю ListA.Except(ListB), я получу возвращенный ExceptIterator, который позволит мне перебирать ListA для любого элемента, которого нет в ListB. Проблема в том, что его реализация состоит в том, чтобы просто использовать ListA (по какой-то причине я думал, что это создаст новую коллекцию элементов, которые являются разницей). Хорошо, но я пришел к выводу, что он все еще использует ListA в качестве источника, но просто использует специальный тип итератора. Поэтому, конечно, когда я удаляю элемент из ListA, он жалуется, что коллекция была изменена.

Я могу придумать пару способов сделать то, что я хочу, во-первых, это скопировать ListA и сделать исключение на копии. Второе - просто сделать цикл while. Мне просто интересно, что является лучшим решением этой проблемы, и что следует стандартным рекомендациям.

Если я пойду не так, я бы хотел это знать. Моя ключевая цель - удалить все данные из DictA, которых нет в DictB, используя ключи в качестве сравнения.

Ответы [ 6 ]

3 голосов
/ 07 июля 2011

Если вам нужен результат, чтобы остаться и не зависеть от последующих изменений, просто получите конкретный результат, вызвав ToList() или ToArray() в запросе.

var query = list1.Except(list2).ToList(); 

Изменения в любом входном источнике не повлияют на ваш теперь полностью оцененный запрос.

2 голосов
/ 07 июля 2011

По той же причине я использую следующее:

ListA = ListA.Except(ListB).ToList();
2 голосов
/ 07 июля 2011

Почему бы просто не использовать нетерпеливые оценки?

var myList = ListA.Except(ListB).ToList();
0 голосов
/ 08 июля 2011

Если вы можете управлять рассматриваемой структурой данных, может быть полезно определить метод Purge, который принимает предикат (функция, которая принимает тип данных списка и возвращает логическое значение) и удаляет все элементы, где предикатвозвращает true (хотелось бы, чтобы Microsoft определила коллекцию IPurgeableCollection, поскольку при реализации такой процедуры для многих из обычных коллекций Microsoft не было бы врожденных трудностей).Обратите внимание, что во многих случаях для коллекции было бы намного проще реализовать метод Purge, чем разрешить общее изменение во время перечисления, и что во многих случаях такой метод мог бы не только избежать необходимости создавать дополнительную копию данных дляудаляются, но это также может значительно сократить объем работы, необходимой для выполнения удалений (например, при очистке словаря не нужно искать каждый удаляемый ключ, поскольку он уже был бы найден во время перечисления).

0 голосов
/ 08 июля 2011

Если вы хотите пересечение двух словарей, то вот что вы делаете:

IEnumerable<KeyValuePair<Char, String>> result = DictB.Intersect<KeyValuePair<Char, String>>(DictA);

Это вернет все элементы в DictA, соответствующие DictB.Кроме того, для примера я предполагаю, что ключи имели тип Char, а значения имели тип String.Если у вас они другие, просто установите правильные типы для вашего решения.Чтобы увидеть фактический результат, вы должны либо отправить result.GetEnumerator (), либо использовать его в выражении foreach.

0 голосов
/ 07 июля 2011

Может быть, вы идете об этом в обратном направлении.Другой способ сказать «удалить все из DictA, который не находится в DictB», это сказать « сохранить все в DictA, которое также находится в DictB».Вместо того, чтобы пытаться удалить вещи из ListA, просто создайте новый список:

ListA.Join(ListB, ...);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...