0

Lets say that I have a List of a custom "Point" class (I know there is one in System.Drawing, but lets say I need a custom one). Now this list can sometimes have the same points, so for example, say it is set up like this:

List<customPoint> myPoints = new List<customPoint>();
myPoints.Add(new customPoint(1,5));
myPoints.Add(new customPoint(1,5));
myPoints.Add(new customPoint(2,3));
myPoints.Add(new customPoint(4,9));
myPoints.Add(new customPoint(8,7));
myPoints.Add(new customPoint(2,3));

And later I need to do some calculation, but I do not need duplicates. What would be a more elegant way to make a new list of unique points than this:

List<customPoint> uniquePoints = new List<customPoint>();

for(int i; i < myPoints.Count; i++)
{
    Boolean foundDuplicate = false;    

    int tempX = myPoints[i].X;
    int tempY = myPoints[i].Y;        

    for(int j=0; j < uniquePoints.Count; j++)
    {
        if((tempX == uniquePoints[0].X) && (tempY == uniquePoints[0].Y))
        {
            foundDuplicate = true;
            break;
        }            
    }
    if(!foundDuplicate)
    {
        uniquePoints.Add(myPoints[i]);
    }        
}

I know it is messy, but that is why I am asking if there is a more elegant way. I looked at the Linq "Distinct" command, but it does not appear to work, I guess there's something in their object instantiation that is still unique.

4

4 回答 4

1

1)将这些方法添加到您的customPoint

public override int GetHashCode()
{
    return X.GetHashCode() * 19 + Y.GetHashCode();
}

public override bool Equals(object obj)
{
    var other = obj as customPoint;
    return this.X == other.X && this.Y == other.Y;
}

您可以使用 Linq 的Distinct方法。

var distinctPoints = myPoints.Distinct().ToList();

2)您可以使用匿名类型比较技巧而不覆盖任何方法。

var distinctPoints = myPoints.GroupBy(m => new { m.X, m.Y })
                             .Select(x => x.First())
                             .ToList();

3)您也可以通过编写自定义来做到这一点IEqualityComparer

public class MyEqualityComparer : IEqualityComparer<customPoint>
{
    public bool Equals(customPoint a, customPoint b)
    {
        return a.X == b.X && a.Y == b.Y;
    }

    public int GetHashCode(customPoint other)
    {
        return other.X.GetHashCode() * 19 + other.Y.GetHashCode();
    }
}

var distinctPoints = myPoints.Distinct(new MyEqualityComparer()).ToList();
于 2013-04-26T18:59:13.880 回答
1

您尝试使用不起作用的 LINQ 做什么?下面的代码应该做到这一点:

var uniquePoints = myPoints.Distinct();
于 2013-04-26T18:54:39.060 回答
0

Distinct方法将是一个很好的方法,但为了按照您的意愿使用它,您必须在您的对象上实现EqualsGetHashCode,或者创建一个IEqualityComparer<customPoint>并将其传递给Distinct方法。对于您的情况,在您的对象上实现这些方法可能是有意义的。从文档中:

默认相等比较器Default用于比较实现IEquatable<T>泛型接口的类型的值。要比较自定义数据类型,您需要实现此接口并为该类型提供您自己的GetHashCodeEquals方法。

于 2013-04-26T18:58:03.530 回答
0

我在 LinqPad 中做到了这一点,所以请原谅Dump()......但是这里有一种实现你的customPoint类的方法:

void Main()
{
    var myPoints = new List<customPoint>();
    myPoints.Add(new customPoint(1,5));
    myPoints.Add(new customPoint(1,5));
    myPoints.Add(new customPoint(2,3));
    myPoints.Add(new customPoint(4,9));
    myPoints.Add(new customPoint(8,7));
    myPoints.Add(new customPoint(2,3));

    myPoints.Distinct().Dump();
}


public class customPoint {
    public int X;
    public int Y;

    public customPoint(int x, int y){
        X = x;
        Y = y;
    }

    public override Boolean Equals(Object rhs) {
        var theObj = rhs as customPoint;

        if(theObj==null) {
            return false;
        } else {
            return theObj.X == this.X && theObj.Y == this.Y;
        }
    }

    public override int GetHashCode() {
        return X ^ Y;
    }
}
于 2013-04-26T19:05:37.683 回答