简体   繁体   English

获取在列表中两次出现exaclty的对象列表

[英]Getting List of Objects that occurs exaclty twice in a list

I have a List<CustomPoint> points; 我有一个List<CustomPoint> points; which contains close to million objects. 其中包含近百万个对象。 From this list I would like to get the List of objects that are occuring exactly twice. 从这个列表中我想得到恰好发生两次的对象列表。 What would be the fastest way to do this? 最快的方法是什么? I would also be interested in a non-Linq option also since I might have to do this in C++ also. 我也会对非Linq选项感兴趣,因为我可能也必须在C ++中这样做。

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

based on this answer, i tried, 基于这个答案,我试过,

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

but this is giving zero objects in the new list. 但是这会在新列表中给出零对象。 Can someone guide me on this? 有人可以指导我吗?

您应该在类本身而不是PointComparer中实现Equals和GetHashCode

要使代码正常工作,您需要将PointComparer的实例作为第二个参数传递给GroupBy

This method works for me: 这个方法适合我:

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

Called like this: 这样称呼:

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 implementation: 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;
    }
}

It prints: 它打印:

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

As you see in GetPointCount() , I create a dictionary per unique CustomPoint (by hash). 正如您在GetPointCount()看到的,我为每个唯一的CustomPoint创建一个字典(通过哈希)。 Then I insert a PointCount object containing a reference to the CustomPoint which starts at a Count of 1, and every time the same point is encountered, the Count is increased. 然后我插入一个PointCount对象,其中包含一个以Count为1开始的CustomPoint的引用,每次遇到相同的点时, Count都会增加。

Finally in GetPointsByCount I return the CustomPoint s in the dictionary where PointCount.Count == count , in your case 2. 最后,在GetPointsByCount我返回CustomPoint字典中的S其中PointCount.Count == count ,你的情况2。

Please also note I updated the GetHashCode() method, since your one returns the same for point (1,2) and (2,1). 还请注意我更新了GetHashCode()方法,因为你的方法为点(1,2)和(2,1)返回相同的方法。 If you do want that, feel free to restore your own hashing method. 如果您确实需要,请随意恢复自己的哈希方法。 You will have to test the hashing function though, because it's hard to uniquely hash two numbers into one. 您必须测试散列函数,因为很难将两个数字唯一地散列为一个。 That depends on the range of numbers used though, so you should implement a hash function that fits your own needs. 这取决于使用的数字范围,因此您应该实现适合您自己需要的哈希函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM