2012-02-15 2 views
7

Извините, что поставил такие основные вопросы, я новичок в LINQ, и я пытаюсь найти лучший способ сделать это, не зацикливая каждый IList.Удалите элементы в одном IList <> из другого IList <>

У меня есть 2 ILists<> с пользовательскими объектами dto. Я хочу удалить все соответствующие элементы из списка, которые находятся в другом.

IList<ItemDTO> list1 = itemsbl.GetBestItems(); 
IList<ItemDTO> list2 = itemsbl.GetWorstItems(); 

Мне нужно удалить все элементы в list1 от list2. Я смотрел на метод Except(), но, видимо, мне нужен мой класс ItemsDTO, чтобы переопределить методыи Equals для этого, но у меня возникли проблемы с поиском некоторых примеров этого.

Может кто-нибудь, пожалуйста, покажет мне лучший способ удалить list1 из list2?

Еще раз спасибо

ответ

9

Вы можете, вероятно, использовать кроме способа сделать это.

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

Если вы хотите, чтобы затем заменить List2 просто сделать это:

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

Из MSDN:

Для сравнения пользовательских типов данных, реализовать IEquatable общего интерфейса и предоставить собственный GetHashCode и Equals для типа . По умолчанию равенство по умолчанию, значение по умолчанию используется для сравнения значений типов, реализующих IEquatable.

+0

Спасибо, я в конечном итоге изменения моего класса, соответственно, так что я могу, кроме нас() ... Спасибо всем, я уверен, что все остальные решения были столь же хороши ...:) – Nugs

1

Хеш это определенно хороший способ, @Jon Skeet ниже ответ на аналогичный вопрос предоставит вам решение.

поэтому в основном синтаксис:

var setToRemove = new HashSet<ItemDTO>(list1); 
list2.RemoveAll(x => setToRemove.Contains(x)); 

Using LINQ to remove elements from a List<T>

надеюсь, что это помогает.

+0

Не знаю почему, но RemoveAll() не является для меня вариантом ... – Nugs

+3

IList - это интерфейс, который List реализует.Илист используется для других классов коллекции. Класс List содержит методы, которые не могут быть определены в IList. Таким образом, назначив свой оригинальный объект списка IList, вы больше не будете иметь доступа к каким-либо уникальным методам List. Если у вас нет причины использовать IList , я бы рекомендовал использовать Список . MSDN: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx – Nickz

1
var list1 = new List<string> { "A", "B", "C" }; 
var list2 = new List<string> { "A", "C", "E", "B", "D", "G", "F" }; 
list2.RemoveAll(list1.Contains); 

будет работать, тоже. Обратите внимание, что список1.Контейнеры на самом деле лямбда

s => list1.Contains(s) 

-A.

+0

Я не знаю почему, но RemoveAll() не является для меня вариантом ... – Nugs

+0

'list.Contains' на самом деле не является лямбда. Хотя он ведет себя одинаково здесь. – svick

+1

Я упомянул об этом, потому что считал важным, что RemoveAll принимает предикат, тем более, что объекты OP могут не иметь реализации равенства/сравнения. – Ani

0

Это означает, что вам нужно указать время выполнения .net, как определить, равны ли два экземпляра класса (например, как определить, является ли один экземпляр ItemDTO равным другому экземпляру ItemDTO).

, чтобы сделать это, переопределение Equals

public class ItemDTO 
{ 
    public override bool Equals(object obj) 
    { 
     var otherItem = obj as ItemDTO; 

     if (otherItem == null) 
     { 
      // this will be because either 'obj' is null or it is not of type ItemDTO. 
      return false; 
     } 

     return otherItem.SomeProperty == this.SomeProperty 
       && otherItem.OtherProperty == this.OtherProperty; 
    } 
} 

Если вы не сделаете этого, то это будет только удалить все ссылки в списке, которые указывают на тот же физический, например, как другой. Затем вы можете использовать методы Except или RemoveAll или любой другой метод, который вы решите использовать.

Вам также необходимо переопределить GetHashcode, см. Ссылку ниже для получения дополнительной информации об этом.

См Guidelines for Overloading Equals and GetHashcode

Смежные вопросы