Удаление предметов из одной коллекции в другую коллекцию - PullRequest
5 голосов
/ 28 октября 2008

У меня есть две коллекции (общие списки), назовем их ListA и ListB.

В ListA у меня есть несколько элементов типа A. В ListB у меня есть несколько элементов типа B, которые имеют ЖЕ ИД (но не того же типа), что и элементы в ListA, и многие другие. Я хочу удалить все элементы из ListB, которые имеют тот же идентификатор, что и в ListA. Какой лучший способ сделать это? Linq для объектов хорошо подходит? Какой алгоритм вы бы использовали?

Пример

Список A: ItemWithID1, ItemWithID2¨

Список B: ItemWithID1, ItemWithID2, ItemWithID3, ItemWithID4

РЕДАКТИРОВАТЬ: я забыл упомянуть в моем первоначальном вопросе, что ListA и ListB не содержат одинаковые типы. Таким образом, единственный способ сравнить их - через свойство .Id. Что делает недействительными ответы, которые я получил до сих пор.

Ответы [ 6 ]

12 голосов
/ 28 октября 2008

Вот два варианта. Не уверен, какой из них быстрее.

listB.RemoveAll(listA.Contains);


foreach (string str in listA.Intersect(listB))
  listB.Remove(str);
3 голосов
/ 04 ноября 2008

Я обнаружил, что лямбда-выражения идеально подходят. Вместо длинного метода linq to objects я мог бы сделать это всего за несколько строк с помощью лямбды:

foreach(TypeA objectA in listA){
    listB.RemoveAll(objectB => objectB.Id == objectA.Id);
}
1 голос
/ 05 января 2009

Я думаю, что лучше всего подходит метод Microserf's

Большинство приведенных выше примеров относятся к ситуациям, когда два списка относятся к одному типу. Но если вы хотите сравнить идентификаторы разных типов и хотите удалить их наилучшим способом, это способ Microserf.

Спасибо

0 голосов
/ 29 октября 2008

Что-то для справки, доступное с C5 Generic Collection Library для .NET - это метод RemoveAll, как было определено ранее Тоддом Уайтом. Тем не менее, C5 также предлагает другой метод в своих интерфейсах, RetainAll, который делает функциональную противоположность RemoveAll в том, что, используя оригинальные списки авторов,

ListB.RetainAll(ListA) - это набор { Item1, Item2 }, тогда как ListB.RemoveAll(ListA) - это набор { Item3, Item4 }.

0 голосов
/ 28 октября 2008

Я не знаю, что это лучший вариант, но если вы удаляете все элементы ListA, которые есть в ListB, просто перебираете ListA и используете конструкцию if ListB.contains, удаляя ее из ListB.

Примерно так

foreach Object o in ListA
  If ListB.contains(o)
    ListB.remove(o)
0 голосов
/ 28 октября 2008

простой цикл:

for (item i: LISTA) {
    removeItem(i, LISTB);
}


method removeItem(Item, List) {
    for (Item i: List) {
        if (Item == i)
            List.removeItem(i);
    }
}
...