如何获取不在另一个列表中的列表元素C#

时间:2013-12-05 00:11:24

标签: c# linq list

我想知道如何获取不属于同一类型的另一个列表的元素。

实施例

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

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

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

我想要一个包含元素A和B的新列表

我试图这样做,但它没有用。

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

2 个答案:

答案 0 :(得分:2)

1)请注意Person可能不是值类型,而是引用类型。因此,Except不会比较值,而是引用。如果你想通过实例的属性应用“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)最后,值得注意的是,如果Personstruct(值类型),那么您的代码将按原样运行,假设所有属性匹配您正在除外的实例。例如:

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

答案 1 :(得分:2)

您拥有的代码很可能无法正常工作,因为它正在进行参考比较,这意味着ABPerson个对象,并且每个属性具有相同的值{{1} }为true,A != B为false。现在,如果我有;

A == B

因此,您可能希望定义自定义相等比较器。你可以这样做;

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

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

然后打电话给Except,就像这样;

   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();
        }
    }