linq GroupBy将<class>列入新的List <class> </class> </class>

时间:2014-04-14 16:22:54

标签: c# linq

我有一个名为Person的类

class Person() {
 string Name;
 string SSN;
}

以及包含许多重复的Person类的常见实例的List。例如

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

由于

2 个答案:

答案 0 :(得分:3)

执行此操作的最佳方法是实现平等(直接在Person或通过IEqualityComparer<Person>),然后执行Distinct。 E.g。

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

答案 1 :(得分:2)

您的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)

编译因为有一个overload for GroupBy,它为键选择器使用lambda,为结果选择器使用另一个lambda。它基本上按Name对您的集合进行了分组,但返回了一组字符串(提取SSN属性)

您要做的是创建一个代表复合键的匿名类型:

.GroupBy(x => new {x.Name, x.SSN})