18

我有一个员工的集合

Class Employee

{
  empName
  empID
  empLoc 
  empPL
  empShift
}

我的清单包含

 empName,empID,empLoc,empPL,empShift
    E1,1,L1,EPL1,S1 
    E2,2,L2,EPL2,S2
    E3,3,L3,EPL3,S3
    E4,4,L1,EPL1,S1
    E5,5,L5,EPL5,S5
        E6,6,L2,EPL2,S2

我需要选择具有不同值 empLoc、empPL、empShift 的员工。

有没有办法使用 LINQ 来实现这一点?

4

5 回答 5

42

您可以使用GroupBy匿名类型,然后获取First

list.GroupBy(e => new { 
                          empLoc = e.empLoc, 
                          empPL = e.empPL, 
                          empShift = e.empShift 
                       })

    .Select(g => g.First());
于 2012-09-25T09:50:41.780 回答
39

您可以实现自定义IEqualityComparer<Employee>

public class Employee
{
    public string empName { get; set; }
    public string empID { get; set; }
    public string empLoc { get; set; }
    public string empPL { get; set; }
    public string empShift { get; set; }

    public class Comparer : IEqualityComparer<Employee>
    {
        public bool Equals(Employee x, Employee y)
        {
            return x.empLoc == y.empLoc
                && x.empPL == y.empPL
                && x.empShift == y.empShift;
        }

        public int GetHashCode(Employee obj)
        {
            unchecked  // overflow is fine
            {
                int hash = 17;
                hash = hash * 23 + (obj.empLoc ?? "").GetHashCode();
                hash = hash * 23 + (obj.empPL ?? "").GetHashCode();
                hash = hash * 23 + (obj.empShift ?? "").GetHashCode();
                return hash;
            }
        }
    }
}

现在您可以使用以下重载Enumerable.Distinct

var distinct = employees.Distinct(new Employee.Comparer());

使用匿名类型的不太可重用、健壮和高效的方法:

var distinctKeys = employees.Select(e => new { e.empLoc, e.empPL, e.empShift })
                            .Distinct();
var joined = from e in employees
             join d in distinctKeys
             on new { e.empLoc, e.empPL, e.empShift } equals d
             select e;
// if you want to replace the original collection
employees = joined.ToList();
于 2012-09-25T09:55:13.333 回答
15

您可以尝试使用此代码

var result =  (from  item in List
              select new 
              {
                 EmpLoc = item.empLoc,
                 EmpPL= item.empPL,
                 EmpShift= item.empShift
              })
              .ToList()
              .Distinct();
于 2012-09-25T09:48:59.520 回答
3

我很好奇哪种方法会更快:

  1. 将 Distinct 与自定义 IEqualityComparer 或
  2. 使用 Cuong Le 描述的 GroupBy 方法。

我发现根据输入数据的大小和组的数量,Distinct 方法的性能可能要高得多。(由于组的数量趋向于列表中的元素数量,因此 distinct 运行得更快)。

代码在 LinqPad 中运行!

    void Main()
    {
        List<C> cs = new List<C>();
        foreach(var i in Enumerable.Range(0,Int16.MaxValue*1000))
        {
            int modValue = Int16.MaxValue; //vary this value to see how the size of groups changes performance characteristics. Try 1, 5, 10, and very large numbers
            int j = i%modValue; 
            cs.Add(new C{I = i, J = j});
        }
        cs.Count ().Dump("Size of input array");

        TestGrouping(cs);
        TestDistinct(cs);
    }

    public void TestGrouping(List<C> cs)
    {
        Stopwatch sw = Stopwatch.StartNew();
        sw.Restart();
        var groupedCount  = cs.GroupBy (o => o.J).Select(s => s.First()).Count();
        groupedCount.Dump("num groups");
        sw.ElapsedMilliseconds.Dump("elapsed time for using grouping");
    }

    public void TestDistinct(List<C> cs)
    {
        Stopwatch sw = Stopwatch.StartNew();
        var distinctCount = cs.Distinct(new CComparerOnJ()).Count ();
        distinctCount.Dump("num distinct");
        sw.ElapsedMilliseconds.Dump("elapsed time for using distinct");
    }

    public class C
    {
        public int I {get; set;}
        public int J {get; set;}
    }

    public class CComparerOnJ : IEqualityComparer<C>
    {
        public bool Equals(C x, C y)
        {
            return x.J.Equals(y.J);
        }

        public int GetHashCode(C obj)
        {
            return obj.J.GetHashCode();
        }
    }
于 2015-03-31T01:50:56.000 回答
0

尝试,

var newList = 
(
from x in empCollection
select new {Loc = x.empLoc, PL = x.empPL, Shift = x.empShift}
).Distinct();
于 2012-09-25T09:50:04.243 回答