在C#中使用LINQ的Distinct方法
在C#中使用LINQ的Distinct方法
我在使用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个对象。
问题的原因是需要从数据库中选择一组数据,并根据其中的某些字段进行分组。然后,对于每个分组,需要选择其中的第一行作为代表。
解决方法是使用LINQ中的Distinct方法。首先,使用Select语句从数据库提供程序中选择所需的数据,并创建PjdGatewayLineChanged对象。然后,使用GroupBy方法将数据按照LineId字段进行分组。最后,使用Select方法选择每个分组中的第一行作为代表。
以下是使用Distinct方法的示例代码:
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());
另一种更简洁的写法是:
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对象的过程被移动到了最后一步,即在选择分组中的合适的"候选者"之后。
问题出现的原因是LINQ和.NET框架不知道如何区分类型为PjdGatewayLineChanged的不同对象。默认情况下,它们会根据内存引用来判断相等性。解决方法是使用Distinct方法的第二个重载,并提供一个实现了IEqualityComparer接口的对象。这样LINQ就能够比较不同的PjdGatewayLineChanged实例了。
以下是使用Distinct方法的第二个重载的示例代码:
public class PjdGatewayLineChangedEqualityComparer : IEqualityComparer{ public bool Equals(PjdGatewayLineChanged x, PjdGatewayLineChanged y) { // Implement your comparison logic here return x.Id == y.Id; // Example: Compare by Id property } public int GetHashCode(PjdGatewayLineChanged obj) { // Implement your hash code generation logic here return obj.Id.GetHashCode(); // Example: Use Id property for hash code } } // Usage IEnumerable distinctItems = items.Distinct(new PjdGatewayLineChangedEqualityComparer());
使用上述代码,我们创建了一个实现了IEqualityComparer接口的PjdGatewayLineChangedEqualityComparer类。在Equals方法中,我们可以根据自己的比较逻辑来判断两个对象是否相等。在GetHashCode方法中,我们可以根据自己的需求生成哈希码。然后,我们可以通过传递这个自定义的比较器对象给Distinct方法来获取不重复的PjdGatewayLineChanged对象的集合。
更多关于IEqualityComparer接口的信息可以参考MSDN文档:[链接](http://msdn.microsoft.com/en-us/library/ms132151.aspx)
使用LINQ Distinct的原因是需要从数据源中筛选出唯一的元素。然而,使用LINQ的Distinct方法只能对整个对象进行比较,而不能对特定属性进行比较。在上述示例中,需要根据LineId属性来筛选出唯一的元素。
解决方法是使用MoreLINQ库中的DistinctBy方法。DistinctBy方法允许根据指定的属性来筛选唯一的元素。在上述示例中,使用DistinctBy(p => p.LineId)来根据LineId属性来筛选唯一的元素。
另一种解决方法是使用GroupBy方法进行分组,然后再使用Select方法选择每组中的第一个元素。这种方法与MoreLINQ库中DistinctBy方法的实现类似,只是在某些平台上使用了Hashset来实现而已。
如果不想引入整个MoreLINQ库,可以直接使用DistinctBy方法的实现。可以在MoreLINQ库的源代码中找到DistinctBy方法的实现,并将其直接使用在项目中(记得注明来源)。
使用LINQ Distinct方法时,如果需要根据特定属性来筛选唯一的元素,可以使用MoreLINQ库中的DistinctBy方法或者使用GroupBy和Select方法的组合来实现。如果不想引入整个MoreLINQ库,可以直接使用DistinctBy方法的实现。