我想使用LINQ删除自定义结构中的重复数据。
这是我的自定义结构:
如您所见,黄色部分认为是需要删除的重复数据。
我首先想到的是使用IEqualityComparer,但似乎无法正常工作。
如果A的形式等于B的To,并且A的To等于B的From,那么将被视为重复数据。
小From将保留,大From将删除
例如,索引5将保留,但索引6将删除。
有人知道如何在LINQ中解决这个问题吗?
答案 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
To
和From
相等的两个范围相等是合理的。
这足以实现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();