Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用LINQ删除自定义结构中的重复数据_Linq_Duplicates - Fatal编程技术网

使用LINQ删除自定义结构中的重复数据

使用LINQ删除自定义结构中的重复数据,linq,duplicates,Linq,Duplicates,我想用LINQ删除自定义结构中的重复数据 以下是我的自定义结构: class Range { public Range(int from, int to) { From = from; To = to; } public int From { get; } public int To { get; } } 正如你所看到的,黄色部分被认为是需要删除的重复数据。 我想到的第一个想法是使用IEqualityComparer,

我想用LINQ删除自定义结构中的重复数据

以下是我的自定义结构:

class Range
{
    public Range(int from, int to)
    {
        From = from;
        To = to;
    }

    public int From { get; }
    public int To { get; }
}

正如你所看到的,黄色部分被认为是需要删除的重复数据。

我想到的第一个想法是使用IEqualityComparer,但它似乎不能很好地工作

如果等于B的形式和等于B的形式,则将考虑重复数据。

小的自会保留,大的自会移除

例如,索引5将保留,但索引6将删除


有人知道如何在LINQ中解决这个问题吗?

您可以使用LINQ过滤数据,以获取所有副本,然后将其删除

我下面的解决方案可能不是最聪明的方法,但请尝试一下

这应该符合您的自定义数据(如果您在问题中指定它,这会有所帮助):

您处理数据的其他地方:

List<CustomStructure> customlist = GetCustomData();
IEnumerable<CustomStructure> dupes = customlist.Where(x => customlist.Any(y => x.From == y.To && x.To == y.From && x.From > y.From));

foreach (CustomStructure dupe in dupes)
{
    customlist.Remove(dupe);
}
List customlist=GetCustomData();
IEnumerable dupes=customlist.Where(x=>customlist.Any(y=>x.From==y.To&&x.To==y.From&&x.From>y.From));
foreach(自定义结构重复中的重复)
{
自定义列表。删除(复制);
}

我这里没有我的Visual Studio,所以这一切都是在没有检查的情况下编写的;希望它能起作用。

感谢@Nicolas提出了一个想法 我认为这是我能得到的最好的方法

listRow.Where(x => listRow.Any(y => x.From < y.From && x.From == y.To && x.To == y.From)).ToList();
listRow.Where(x=>listRow.Any(y=>x.From
我将使用范围而不是“自定义结构”:

使用IEqualityComparer,但似乎无法正常工作

也许是因为“相等”不能简单地通过相等一个(或两个)
范围
属性来定义?但你(几乎)完美地定义了平等

x.From == y.To && x.To == y.From
我认为这应该由……来修正

x.From == y.From && x.To == y.To
似乎合理的是,具有相等的<代码>到<代码>和<代码>从<代码>的两个范围是相等的

这足以实现
IEqualityComparer
Equals
方法

然而,实现
GetHashCode
的挑战始终是它应该匹配
Equals
方法——这里定义的相等应该导致相同的哈希值——但现在基于一个对象实例的属性

第一个脉冲是将哈希基于
从+到
。但这将使
范围(8,5)
等于
范围(7,6)
。这也可以通过将
From-To
引入方程来解决。当<代码>从+到<代码>相等时,以及当从-到<代码>的绝对差值相等时,两个范围相等:

x.From + x.To == y.From  + y.To
    && Math.Abs( x.From - x.To) == Math.Abs(y.From  - y.To);
这是基于等式两侧单个实例的属性的等式,因此现在我们可以实现
GetHashCode
。以下内容(并在Resharper的帮助下):

和完整的比较器:

class RangeEqualityComparer : IEqualityComparer<Range>
{
    public bool Equals(Range x, Range y)
    {
        return y != null
               && x != null
               && x.From + x.To == y.From  + y.To
               && Math.Abs( x.From - x.To) == Math.Abs(y.From  - y.To);
    }

    public int GetHashCode(Range obj)
    {
        var hashCode = -1781160927;
        hashCode = hashCode * -1521134295 + (obj.From + obj.To).GetHashCode();
        hashCode = hashCode * -1521134295 + (Math.Abs(obj.From - obj.To)).GetHashCode();
        return hashCode;
    }
}

排序定义了“相等”的范围范围将出现在最终结果中。

条件
x.From>y.From
应仅包括具有较高
From
值的复制记录-只需添加一些调试打印输出,以确定哪些记录作为复制返回,然后您可以手动对照它们检查验证逻辑是的,我知道您的意思,这似乎有效。但不是流畅的解决方法。无论如何,谢谢你,我知道你的想法了。为什么
IEqualityComparer
似乎工作不好?如果使用IEqualityComparer,我需要在自定义结构中添加一个extract属性,还需要添加一个classYou不需要“精确”属性。您确实需要一个类,但这不是使用相等比较器的想法吗(不确定我是否理解)。查看我的答案。选择从、到、从<到?(from+|+to):(to+|+from)作为键与键不同的键,我认为它更好,你不这样认为吗?对不起,我不知道你在这里说什么。如果你问带有
Where
子句的解是否更好,我会说不,因为它必须计算列表中每个元素的
Where
条件(
list.Where(x=>列表。任何(…
)表示O(N²)与接近O(N)对于比较器。很抱歉回答,我的工作得到了OT。我要说的是添加一个属性来标识类。使用From和to组合到属性,然后您可以分组,最终区分。没有一个属性可以充分标识相等或不相等,因为From+Two的更多组合会产生相同的和。即使您将hashcode计算用作Range类的GetHashCode方法,也不会。这些哈希值可能会发生冲突(=碰巧相等,但不应该相等)。这就是您需要比较器的原因。当哈希相等时,比较器总是执行
Equals
。您还提到了分组。对于分组,您可以使用相同的比较器。无需一直编写复杂的LINQ语句。
public int GetHashCode(Range obj)
{
    var hashCode = -1781160927;
    hashCode = hashCode * -1521134295 + (obj.From + obj.To).GetHashCode();
    hashCode = hashCode * -1521134295 + (Math.Abs(obj.From - obj.To)).GetHashCode();
    return hashCode;
}
class RangeEqualityComparer : IEqualityComparer<Range>
{
    public bool Equals(Range x, Range y)
    {
        return y != null
               && x != null
               && x.From + x.To == y.From  + y.To
               && Math.Abs( x.From - x.To) == Math.Abs(y.From  - y.To);
    }

    public int GetHashCode(Range obj)
    {
        var hashCode = -1781160927;
        hashCode = hashCode * -1521134295 + (obj.From + obj.To).GetHashCode();
        hashCode = hashCode * -1521134295 + (Math.Abs(obj.From - obj.To)).GetHashCode();
        return hashCode;
    }
}
ranges.OrderBy(r => r.From).Distinct(new RangeEqualityComparer())