在C#中使用LINQ Distinct

本文关键字:LINQ Distinct | 更新日期: 2023-09-27 18:26:31

我在LINQ中使用distinct时遇到问题。我有这个清单:

LineIdChanged   LineId  OldGatewayPCId  NewGatewayPCId  LineStringID    PlantID
1               93      83              88              160             2
2               93      83              88              161             2
3               94      82              87              162             2
4               94      82              87              163             2

我所尝试的是获得一个不同的LineId值,所以在这种情况下,我应该只获得两个对象,而不是所有四个对象。我试过这个:

  var s = (from n in _dataBaseProvider.SelectPjdGatewayLineChanged(selectedSourcePlant.LPS_Database_ID)
          select new PjdGatewayLineChanged() { LineId = n.LineId, LpsLineNo = n.LpsLineNo, LineIdChanged = n.LineIdChanged}).Distinct();
  LinesOld = s.ToList();

但这给了我所有的4个对象。

在C#中使用LINQ Distinct

您需要使用MoreLINQ的DistinctBy:

var s = 
    (from n in _dataBaseProvider.SelectPjdGatewayLineChanged
    (selectedSourcePlant.LPS_Database_ID)
    select new PjdGatewayLineChanged
    { 
        LineId = n.LineId,
        LpsLineNo = n.LpsLineNo, 
        LineIdChanged = n.LineIdChanged
    })
    .DistinctBy(p => p.LineId);

您的问题是LINQ和.Net框架不知道如何区分PjdGatewayLineChanged类型的不同对象。因此,它使用默认的方法,即在内存引用方面寻找相等性。

因此,您需要使用此方法的第二个重载,并提供IEqualityComparer

参见此处

Distinct<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)

以便LINQ知道如何比较PjdGatewayLineChanged类型的不同实例
IEqualityComparer 的msdn链接

如果您认为所有行都相等,如果它们有一些字段相等:

var s = (from p in _dataBaseProvider.SelectPjdGatewayLineChanged(selectedSourcePlant.LPS_Database_ID)
    select new PjdGatewayLineChanged() 
    { 
        LineId = p.LineId,
        LpsLineNo = p.LpsLineNo, 
        LineIdChanged = p.LineIdChanged
    })
    .GroupBy(p => p.LineId)
    .Select(p => p.First());

你按你的id分组,然后每组都排在第一行。

或者更紧凑的

var s = from p in _dataBaseProvider.SelectPjdGatewayLineChanged(selectedSourcePlant.LPS_Database_ID)
    group p by p.LineId into q
    let r = q.First()
    select new PjdGatewayLineChanged() 
    { 
        LineId = r.LineId,
        LpsLineNo = r.LpsLineNo, 
        LineIdChanged = r.LineIdChanged
    };

通过这种方式,PjdGatewayLineChanged的创建已移至最后一步(在选择groupby.

的正确"候选者"之后

事情是这样的。Distinct(IEnumerable)方法返回一个不包含重复值的无序序列。它使用默认的相等比较器default来比较值。

有两个选项可以将.Distinct()与您的自定义类型一起使用:

  1. PjdGatewayLineChanged提供您自己的GetHashCode和Equals方法
  2. 将重载的Distinct与自定义相等比较器一起使用

有关更多信息,请查看MSDN For Distinct查看MSDN For Distinct,您会发现很好的文档代码片段,这些代码片段将帮助您实现所需的功能。