使用C#中的LINQ从列表中选择不同的值

时间:2012-09-25 09:46:18

标签: c# .net linq

我有一个员工

的集合
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实现这个目的?

5 个答案:

答案 0 :(得分:38)

您可以实施自定义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();

答案 1 :(得分:35)

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

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

    .Select(g => g.First());

答案 2 :(得分:11)

您可以尝试使用此代码

var result =  (from  item in List
              select new 
              {
                 EmpLoc = item.empLoc,
                 EmpPL= item.empPL,
                 EmpShift= item.empShift
              })
              .ToList()
              .Distinct();

答案 3 :(得分:3)

我很想知道哪种方法会更快:

  1. 使用与自定义IEqualityComparer或
  2. 的区别
  3. 使用Cuong Le。描述的GroupBy方法。
  4. 我发现根据输入数据的大小和组的数量,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();
            }
        }
    

答案 4 :(得分:0)

尝试,

var newList = 
(
from x in empCollection
select new {Loc = x.empLoc, PL = x.empPL, Shift = x.empShift}
).Distinct();