2013-12-05 1 views
2

Я хочу знать, как получить элементы, которые не входят в другой список того же типа.Как получить элементы списка, которые не входят в другой список C#

Пример

List<Person> list1; 
List<Person> list2; 

list1[0] = "A" 
list1[1] = "B" 
list1[2] = "C" 
list1[3] = "D" 

list2[0] = "C" 
list2[1] = "D" 

Я хочу, чтобы новый список с элементами А и В

Я пытался это сделать, но это не работает.

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

Что не работает? – StriplingWarrior

+1

Да, это должно работать, если вы используете пространство имен System.Linq – RebelFist

ответ

2

1) Обратите внимание, что Person, скорее всего, не тип значения, но ссылочный тип. Поэтому Except не будет сравнивать значения, а скорее ссылки. Если вы хотите применить «кроме» логики свойство экземпляров (скажем, «Name»), а затем использовать что-то вроде этого:

string[] valuesToExclude = list1.Select(person => person.Name).ToArray(); 
var newList = list2.Where(person => !valuesToExclude.Contains(person.Name)).ToList(); 

2) в качестве альтернативы Вы можете передать IEqualityComparer<Person> в Except:

public class PersonComparer : IEqualityComparer<Person> 
{ 
    public bool Equals(Person x, Person y) 
    { 
     return Equals(x.Name, y.Name); 
    } 

    public int GetHashCode(Person obj) 
    { 
     return obj.Name.GetHashCode(); 
    } 
} 

это второй параметр, как:

var newList = list2.Except(list1, new PersonComparer()).ToList(); 

3) И, наконец, стоит отметить, что если Person были в struct (тип значения), тогда ваш код будет работать как есть, , предполагая, что все свойства соответствуют выбранным вами экземплярам. Например:

public struct Person 
{ 
    public string Name { get; set; } 
} 

List<Person> list1 = new List<Person> 
{ 
    new Person { Name = "A" }, 
    new Person { Name = "B" }, 
}; 
List<Person> list2 = new List<Person> 
{ 
    new Person { Name = "A" }, 
}; 
var newList = list1.Except(list2).ToList(); 
    // "B" only 
2

код у вас есть, скорее всего, не работает, потому что это делает ссылочные сравнения, то есть, если A и B являются Person объектами и имеет то же значение для каждого свойства A != B является истинным и A == B является ложным. Теперь, если бы у меня было;

Person A = new Person(); 
Person B = A; 

A == B // this is true now, that's the comparison Except is doing 

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

class PersonEqualityComparer : IEqualityComparer<Person> 
    { 
     public bool Equals(Person lhs, Person rhs) 
     { 
      return lhs.Name == rhs.Name; 
     } 

     public int GetHashCode(Person p) 
     { 
      return p.Name.GetHashCode(); 
     } 
    } 

Тогда позвоните За исключением так;

var diff = list1.Except(list2, new PersonEqualityComparer()); 
+0

выглядит интересно –

+0

@jimtollan вы можете расширить? Значит, вы думаете, что есть проблема с моим кодом, или это просто не тот подход, с которым вы знакомы? – evanmcdonnal

+0

evan - это приятный прием на компаньоне и, вероятно, тот, который был бы взвинчен над моей головой, если бы я сел, чтобы подумать об этом ... очень приятно и +1 для ваших усилий ... –

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