我有一个名为Person 的类
class Person() {
string Name;
string SSN;
}
以及一个包含许多重复的Person类常见实例的列表。例如
Person.Name = "John";
Person.SSN = "123456789";
Person.Name = "John";
Person.SSN = "123456789";
Person.Name = "John";
Person.SSN = "123456789";
Person.Name = "John";
Person.SSN = "123456789";
Person.Name = "John";
Person.SSN = "123456789";
我正试图弄清楚Linq语句的语法,只需在常见时获取List中的一个类对象,并将其添加到新列表中。
List<Person> newPerson = new List<Person>();
newPerson.AddRange(person.GroupBy(x => x.Name, x => x.SSN).Select(grp => grp.ToList().First()).ToList());
感谢
最好的方法是实现相等(直接在Person
中,或通过IEqualityComparer<Person>
),然后执行Distinct
。例如
class Person : IEquatable<Person> {
// these should be properties, e.g. public string Name { get; set; }
string Name;
string SSN;
public override int GetHashCode() {
// XOR is not the best generally, but can work for something like this
return Name.GetHashCode() ^ SSN.GetHashCode();
}
public override bool Equals(object other) {
return Equals(other as Person);
}
public bool Equals(Person other) {
return other != null && this.Name == other.Name && this.SSN == other.SSN;
}
}
var newPerson = person.Distinct().ToList();
您的GroupBy
语法有点偏离,您不需要所有的ToList
调用:
newPerson.AddRange(person.GroupBy(x => new {x.Name, x.SSN})
.Select(grp => grp.First()));
或者只是
newPerson = person.GroupBy(x => new {x.Name, x.SSN})
.Select(grp => grp.First())
.ToList();
因为无论如何你都是从一个空列表开始的。
详细解释
您的原始语法:
.GroupBy(x => x.Name, x => x.SSN)
编译,因为GroupBy
有一个重载,它为键选择器取一个lambda,为结果选择器取另一个lambda。它基本上按Name
对集合进行分组,但返回了一个字符串集合(提取SSN
属性)
你想做的是创建一个匿名类型来表示你的复合密钥:
.GroupBy(x => new {x.Name, x.SSN})