在列表中查找不同的点(使用2个谓词)

时间:2013-04-26 18:50:48

标签: c# linq duplicates

让我们说我有一个自定义“Point”类的列表(我知道System.Drawing中有一个,但我想我需要一个自定义类)。现在这个列表有时可以有相同的点,例如,假设它设置如下:

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

后来我需要做一些计算,但我不需要重复。制作一个新的独特点列表比这更优雅的方法是什么:

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

我知道它很乱,但这就是为什么我在问是否有更优雅的方式。我查看了Linq“Distinct”命令,但它似乎不起作用,我猜他们的对象实例化中仍有一些东西仍然是唯一的。

4 个答案:

答案 0 :(得分:1)

你尝试使用哪种LINQ无法正常工作?下面的代码应该这样做:

var uniquePoints = myPoints.Distinct();

答案 1 :(得分: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();

答案 2 :(得分:0)

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

  

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

答案 3 :(得分: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;
    }
}