如何在C#列表中删除重复项

3
我有一个基于x和y位置的位置列表,我正在计算两个位置之间的差异。例如,我有像(0,1),(1,0)和(1,2),(2,1)以及(2,3),(3,2)这样的重复项。我想从我的列表中删除所有这些重复项以实现我的目标。有没有一种简单的方法来做到这一点?我一直在尝试构建一个算法,但这很困难。因为我有大约90个位置,不容易确定何时会出现重复。

你想删除除了一个之外的所有吗? - Tim Schmelter
不,我确实想要删除相反的位置,因为我正在计算它们之间的差异并且它们会给出相同的结果。因此,如果我有(0,1)和(1,0),我想要删除(1,0)。@TimSchmelter - Ugur Yilmaz
1
(1,0)和(0,1)如何是重复的? - Jeroen van Langen
1
当您的比较器将反射对视为相等时,@JeroenvanLangen。 - Scott Chamberlain
2个回答

7
最简单的解决方案是为您的点类创建一个IEqualityComparer,它不关心您的XY的顺序,然后您可以使用Distinct来消除重复项。
public class MyPoint
{
    public int X { get; set; }
    public int Y { get; set; }
}

public class PointComparer : IEqualityComparer<MyPoint>
{
    public bool Equals(MyPoint x, MyPoint y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (ReferenceEquals(x, null)) return false;
        if (ReferenceEquals(y, null)) return false;
        return (x.X == y.X && x.Y == y.Y) ||
               (x.X == y.Y && x.Y == y.X);
    }

    public int GetHashCode(MyPoint obj)
    {
        return (obj?.X.GetHashCode() ?? 0) ^ (obj?.Y.GetHashCode() ?? 0);
    }
}

class Program
{
    static void Main()
    {
        List<MyPoint> data = GetDataFromSomewhere();

        var singularData = data.Distinct(new PointComparer()).ToList();
    }
}

2
我会使用带有自定义比较器的Enumerable.Distinct来实现这个逻辑:
public class OppositeLocationsEqualComparer : IEqualityComparer<Location>
{
    public bool Equals(Location l1, Location l2)
    {
        if (object.ReferenceEquals(l1, l2)) return true;
        if (l1 == null || l2 == null) return false;
        return (l1.X == l2.X && l1.Y == l2.Y) || (l1.X == l2.Y && l1.Y == l2.X);
    }

    public int GetHashCode(Location l)
    {
        if(l == null) return int.MinValue;
        return Math.Abs(l.X - l.Y);
    }
}

现在您可以使用Enumerable.Distinct(以及许多其他LINQ方法)与此比较器一起:

List<Location> uniqueLocations = locationList
    .Distinct(new OppositeLocationsEqualComparer())
    .ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接