11

私はList<CustomPoint> points;百万近くのオブジェクトを含む を持っています。このリストから、正確に 2 回発生しているオブジェクトのリストを取得したいと考えています。これを行う最速の方法は何ですか?C++でもこれを行う必要があるかもしれないので、Linq以外のオプションにも興味があります。

public class CustomPoint
{
    public double X { get; set; }
    public double Y { get; set; }

    public CustomPoint(double x, double y)
    {
        this.X = x;
        this.Y = y;
    }
}

public class PointComparer : IEqualityComparer<CustomPoint>
{
    public bool Equals(CustomPoint x, CustomPoint y)
    {
        return ((x.X == y.X) && (y.Y == x.Y));
    }

    public int GetHashCode(CustomPoint obj)
    {
        int hash = 0;
        hash ^= obj.X.GetHashCode();
        hash ^= obj.Y.GetHashCode();
        return hash;
    }
}

この答えに基づいて、私は試しました、

list.GroupBy(x => x).Where(x => x.Count() = 2).Select(x => x.Key).ToList(); 

しかし、これは新しいリストにゼロのオブジェクトを与えています。誰かがこれについて私を案内できますか?

4

3 に答える 3

9

PointComparerではなく、クラス自体にEqualsとGetHashCodeを実装する必要があります

于 2012-12-20T12:02:00.673 に答える
4

PointComparerコードを機能させるには、のインスタンスを2番目の引数としてに渡す必要がありますGroupBy

于 2012-12-20T12:01:40.283 に答える
3

この方法は私のために働きます:

public class PointCount
{
    public CustomPoint Point { get; set; }
    public int Count { get; set; }
}

private static IEnumerable<CustomPoint> GetPointsByCount(Dictionary<int, PointCount> pointcount, int count)
{
    return pointcount
                    .Where(p => p.Value.Count == count)
                    .Select(p => p.Value.Point);
}

private static Dictionary<int, PointCount> GetPointCount(List<CustomPoint> pointList)
{
    var allPoints = new Dictionary<int, PointCount>();

    foreach (var point in pointList)
    {
        int hash = point.GetHashCode();

        if (allPoints.ContainsKey(hash))
        {
            allPoints[hash].Count++;
        }
        else
        {
            allPoints.Add(hash, new PointCount { Point = point, Count = 1 });
        }
    }

    return allPoints;
}

このように呼ばれます:

static void Main(string[] args)
{
    List<CustomPoint> list1 = CreateCustomPointList();

    var doubles = GetPointsByCount(GetPointCount(list1), 2);

    Console.WriteLine("Doubles:");
    foreach (var point in doubles)
    {
        Console.WriteLine("X: {0}, Y: {1}", point.X, point.Y);
    }
}

private static List<CustomPoint> CreateCustomPointList()
{
    var result = new List<CustomPoint>();

    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            result.Add(new CustomPoint(i, j));
        }
    }

    result.Add(new CustomPoint(1, 3));
    result.Add(new CustomPoint(3, 3));
    result.Add(new CustomPoint(0, 2));

    return result;
}

CustomPoint実装:

public class CustomPoint
{
    public double X { get; set; }
    public double Y { get; set; }

    public CustomPoint(double x, double y)
    {
        this.X = x;
        this.Y = y;
    }

    public override bool Equals(object obj)
    {
        var other = obj as CustomPoint;

        if (other == null)
        {
            return base.Equals(obj);
        }

        return ((this.X == other.X) && (this.Y == other.Y));
    }

    public override int GetHashCode()
    {
        int hash = 23;
        hash = hash * 31 + this.X.GetHashCode();
        hash = hash * 31 + this.Y.GetHashCode();
        return hash;
    }
}

それは印刷します:

Doubles:
X: 0, Y: 2
X: 1, Y: 3
X: 3, Y: 3

でわかるように、私は(ハッシュによって)GetPointCount()一意ごとに辞書を作成します。次に、aから始まるへの参照を含むオブジェクトをCustomPoint挿入します。同じポイントに遭遇するたびに、が増加します。PointCountCustomPointCountCount

最後に、辞書のsGetPointsByCountを返します。ここで、あなたの場合は2です。CustomPointPointCount.Count == count

GetHashCode()また、ポイント(1,2)と(2,1)で同じ結果が返されるため、メソッドを更新したことにも注意してください。それが必要な場合は、独自のハッシュメソッドを自由に復元してください。ただし、2つの数値を1つに一意にハッシュすることは難しいため、ハッシュ関数をテストする必要があります。ただし、使用する数値の範囲によって異なるため、自分のニーズに合ったハッシュ関数を実装する必要があります。

于 2012-12-20T12:26:21.000 に答える