C# 使用LINQ筛选类型集合中的重复项

C# 使用LINQ筛选类型集合中的重复项,c#,.net,linq,duplicates,filtering,C#,.net,Linq,Duplicates,Filtering,我通过对两个参数进行分组并基于createdate(使用first())在子grouplist中选择最新的类型来过滤列表。 这将消除x.application和x.externalid属性上的重复项 var list = ((List<SomeType>)xDic) .GroupBy(x => new {x.Application, x.ExternalID}) .OrderByDescending(z => z.First

我通过对两个参数进行分组并基于createdate(使用first())在子grouplist中选择最新的类型来过滤列表。 这将消除x.application和x.externalid属性上的重复项

var list = ((List<SomeType>)xDic)
            .GroupBy(x => new {x.Application, x.ExternalID})
            .OrderByDescending(z => z.First().CreateDate)
            .Select(y => y.First()).ToList();

首先,声明两个相等比较器以指定以下两个条件:

public class MyEqualityComparer1 : IEqualityComparer<SomeType>
{
    public bool Equals(SomeType x, SomeType y)
    {
        return x.Application == y.Application && x.ExternalID == y.ExternalID;
    }

    public int GetHashCode(SomeType obj)
    {
        return (obj.Application + obj.ExternalID).GetHashCode();
    }
}

public class MyEqualityComparer2 : IEqualityComparer<SomeType>
{
    public bool Equals(SomeType x, SomeType y)
    {
        return x.Application == y.Application && x.ExternalDisplayId == y.ExternalDisplayId;
    }

    public int GetHashCode(SomeType obj)
    {
        return (obj.Application + obj.ExternalDisplayId).GetHashCode();
    }
}
var result = xDic
    .OrderByDescending(x => x.CreateDate)
    .Distinct(new MyEqualityComparer1())
    .Distinct(new MyEqualityComparer2());
public static class Extensions
{
    public static IEnumerable<T> OrderedDistinct<T>(this IEnumerable<T> enumerable, IEqualityComparer<T> comparer)
    {
        HashSet<T> hash_set = new HashSet<T>(comparer);

        foreach(var item in enumerable)
            if (hash_set.Add(item))
                yield return item;
    }
}
var result = xDic
    .OrderByDescending(x => x.CreateDate)
    .OrderedDistinct(new MyEqualityComparer1())
    .OrderedDistinct(new MyEqualityComparer2());
Distinct
方法,因此我们应该能够依靠使用
OrderByDescending
来确保
Distinct
将删除具有较短
CreatedTime
的项

但是,由于
Distinct
的文档不能保证这一点,因此可以使用如下自定义Distinct方法:

public class MyEqualityComparer1 : IEqualityComparer<SomeType>
{
    public bool Equals(SomeType x, SomeType y)
    {
        return x.Application == y.Application && x.ExternalID == y.ExternalID;
    }

    public int GetHashCode(SomeType obj)
    {
        return (obj.Application + obj.ExternalID).GetHashCode();
    }
}

public class MyEqualityComparer2 : IEqualityComparer<SomeType>
{
    public bool Equals(SomeType x, SomeType y)
    {
        return x.Application == y.Application && x.ExternalDisplayId == y.ExternalDisplayId;
    }

    public int GetHashCode(SomeType obj)
    {
        return (obj.Application + obj.ExternalDisplayId).GetHashCode();
    }
}
var result = xDic
    .OrderByDescending(x => x.CreateDate)
    .Distinct(new MyEqualityComparer1())
    .Distinct(new MyEqualityComparer2());
public static class Extensions
{
    public static IEnumerable<T> OrderedDistinct<T>(this IEnumerable<T> enumerable, IEqualityComparer<T> comparer)
    {
        HashSet<T> hash_set = new HashSet<T>(comparer);

        foreach(var item in enumerable)
            if (hash_set.Add(item))
                yield return item;
    }
}
var result = xDic
    .OrderByDescending(x => x.CreateDate)
    .OrderedDistinct(new MyEqualityComparer1())
    .OrderedDistinct(new MyEqualityComparer2());

当前接受的答案不会对“SomeType”对象进行正确排序,因此不会生成所需的结果集

我在这里实施了一个解决方案:

我的解决方案也基于Distinct(参见MSDN文档)。我生成散列的方法基于使用匿名类型的整洁方法,例如

public int GetHashCode(SomeType sometype)
{
 //Calculate the hash code for the SomeType.
 return new { sometype.Application, sometype.ExternalID }.GetHashCode();
}
为了获得正确的预期结果,需要将分组、排序和使用不同的方法相结合,例如:

    var noduplicates = products.GroupBy(x => new {x.Application, x.ExternalDisplayId})
        .Select(y => y.OrderByDescending(x => x.CreateDate).First())
        .ToList()
        .Distinct(new ApplicationExternalDisplayIdComparer())
        .GroupBy(x => new {x.Application, x.ExternalID})
        .Select(y => y.OrderByDescending(x => x.CreateDate).First())
        .ToList()
        .Distinct(new ApplicationExternalIDComparer());

正如您将在fiddle输出中看到的,这给出了您期望的结果。

我正试图理解您的问题。你能提供你的类(
SomeType
)的定义吗?看起来像是@B.ClayShannon的副本(但不完全确定)-我必须考虑最近的createdate维度,所以distinct不能完全解决我的问题。你能准确解释
((x.application/x.externalid)或(x.application/x.externaldisplayid))组合
的意思是什么?我怀疑你无法解释你想要什么的事实是问题:)这三个重复项都是{A1,id1,disp1},{A1,id1,disp2},{A1,id2,disp2}?谢谢你的回复@Yacoub。我一有机会就会试试。有趣的-确实是
Distinct(x=>{x.p1})。Distinct(x=>{x.p2})
给出与
Distinct(x=>{x.p2})相同的结果。Distinct(x=>{x.p1})
(这对于OP所寻找的应该是正确的)。@AlexeiLevenkov,是的。所有重复项都将被删除,这是通过调用两个
Distinct
操作来保证的(无论调用顺序如何)。剩下的唯一一件事就是确保我们总是删除最新的项目。由于我们对列表进行了排序,因此我们可以确定,任何
Distinct
操作删除的任何项在序列的前面都有一个类似的项,与最近的
CreatedDate
类似。为什么您认为我的回答没有正确地对对象进行排序?你能解释一下吗?嗨,雅库布。我以与您相同的方式实现了该解决方案,但我发现在执行不同语句之前简单地排序日期并不能得到OP所需的结果。试着把你的答案编成一张.NET的小提琴,并在他的问题中使用OP的示例数据,你会发现你所做的不会给出他预期的结果。你好,本。它是。它给出了相同的结果。我认为OP希望结果的顺序与他在问题中指定的完全相同。要实现这种排序,您需要分组,按日期排序,然后应用distinct。我也有你的小提琴给出的结果集,但我认为OP需要指定的顺序;我的答案是按顺序给出结果的,我明白了。在我看来OP并没有这样的要求。