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

时间:2018-12-22 19:03:30

标签: linq duplicates

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

这是我的自定义结构:

enter image description here

如您所见,黄色部分认为是需要删除的重复数据。

我首先想到的是使用IEqualityComparer,但似乎无法正常工作。

如果A的形式等于B的To,并且A的To等于B的From,那么将被视为重复数据。

小From将保留,大From将删除

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

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

3 个答案:

答案 0 :(得分:1)

您可以使用linq过滤数据以获取所有重复项,然后将其删除。

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

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

public class CustomStructure
{
    public int From { get; set; }
    public int To { get; set; }
    public int Sum { get { return From + To; } }
}

在其他地方使用数据:

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);
}

我在这里没有我的Visual Studio,因此所有内容都编写时没有检查;希望它能起作用。

答案 1 :(得分:1)

我将使用Range代替“自定义结构”:

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

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

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

也许是因为不能通过将Range属性中的一个(或两个)等同来简单地定义“平等”吗?但是您(几乎)完美地定义了平等……

x.From == y.To && x.To == y.From

我认为这应该通过...

进行修改
x.From == y.From && x.To == y.To

ToFrom相等的两个范围相等是合理的。

这足以实现IEqualityComparer的{​​{1}}方法。

但是,实现Equals的挑战总是要使其与GetHashCode方法相匹配-在那里定义的相等应导致相同的哈希值-但现在基于一个对象实例的属性。

第一个冲动是将散列基于Equals。但这会使From + To等于range(8,5)。这也可以通过将range(7,6)引入方程式来解决。当From - To等于时,两个范围是相等的;当绝对差From + To等于时,两个范围是相等的:

From - To

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

GetHashCode

还有完整的比较器:

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;
    }
}

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

答案 2 :(得分:0)

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

listRow.Where(x => listRow.Any(y => x.From < y.From && x.From == y.To && x.To == y.From)).ToList();