簡體   English   中英

使用映射從點集合中刪除重復項

[英]Removing duplicates from collection of points, with mapping

我有一個點數組,我們稱之為rawPoints,其中包含重復項。 實際上,幾乎每個點都重復了2到6次。 某處重復,而不是在連續的位置。 我想刪除重復項以獲得一個新的集合,我稱之為goodPoints。 另外, 我想知道從rawPoints到goodPoints的映射。 換句話說,對於rawPoints中的每個點P,我想知道(唯一)索引i,使得goodPoints [i] = P.

我在C#編碼,所以我想知道是否有任何.NET集合可以幫助解決這個問題。

我已經讀過使用HashSet是刪除重復項的好方法。 但這不會給我映射。

一種可能的解決方案是“AddorFind(P)”函數,我可以使用它將點P添加到goodPoints。 如果P還不是goodPoints的成員,那么AddorFind(P)將添加它。 如果P已經是goodPoints的成員,則AddorFind(P)將返回索引i,使得goodPoints [i] = P.

有類似的東西存在,還是有其他簡單而合理的快速解決方案?

雖然HashSet<Point>無法幫助在goodPoints找到唯一索引, goodPoints Dictionary<Point,int>會。

除了List<Point> goodPoints ,還要創建一個字典Dictionary<Point,int> mappings ,它將點Dictionary<Point,int> mappingsgoodPoints列表中的索引。 當您瀏覽rawPoints數組時,請遵循以下算法:

  • 檢查rawPoints[i]是否在mappings 如果是,繼續下一點
  • 否則,將當前長度的goodPoints添加到rawPoints[i] mappings中,然后將rawPoints[i]添加到gooodPoints列表中。

假設您的Point表示具有良好的散列函數,並且它正確地覆蓋了Equals ,則此算法會生成goodPoints列表和O(N)中的映射。

您將需要兩個輸出:

  1. “好點”列表。
  2. 優點數組中的索引數組,與原始點的長度相同(因為您希望將每個原始點索引映射到優點數組)。

我認為這段代碼會生成以下兩件事:

using System;
using System.Collections.Generic;
using System.Drawing;

namespace Demo
{
    class Program
    {
        static void Main()
        {
            var rawPoints = createRandomPoints(10000, 100, 100);

            int[] goodPointMap = new int[rawPoints.Length];
            var map = new Dictionary<Point, int>();
            var goodPoints = new List<Point>();

            for (int i = 0; i < rawPoints.Length; ++i)
            {
                Point p = rawPoints[i];
                int index;

                if (map.TryGetValue(p, out index))
                {
                    goodPointMap[i] = index;
                }
                else
                {
                    map[p] = goodPoints.Count;
                    goodPointMap[i] = goodPoints.Count;
                    goodPoints.Add(p);
                }
            }

            // At this point we no longer need 'map', which is used only to generate 'goodPoints[]'
            // and 'goodPointMap[]'.

            Console.WriteLine("Number of good points = " + goodPoints.Count);

            // Every point in rawPoints[] should have a point in goodPoints
            // which you can reference via goodPointMap[].
            // Let's verify that:

            for (int i = 0; i < rawPoints.Length; ++i)
                if (rawPoints[i] != goodPoints[goodPointMap[i]])
                    Console.WriteLine("Failed!");
        }

        static Point[] createRandomPoints(int n, int maxX, int maxY)
        {
            var rng    = new Random();
            var result = new Point[n];

            for (int i = 0; i < n; ++i)
                result[i] = new Point(rng.Next(maxX), rng.Next(maxY));

            return result;
        }
    }
}

您可以使用Linq完成此任務:

List<Point> points = new List<Point>();
points.Add(new Point(1, 1));
points.Add(new Point(1, 1));
points.Add(new Point(1, 1));
points.Add(new Point(1, 2));
points.Add(new Point(1, 2));
points.Add(new Point(1, 2));

List<Point> goodPoints = new List<Point>();


foreach (Point p in points)
{
    goodPoints.Add(p);
    //goodPoints = goodPoints.Distinct().ToList();
    //int idx = goodPoints.IndexOf(p);
    int idx = (goodPoints = goodPoints.Distinct().ToList()).IndexOf(p);
    Debug.WriteLine(string.Format("Index of Point({0}, {1}) = {2}", p.X, p.Y, idx));
}

您可以創建一個PointComparer類,並在Distinct方法中使用它。

public class PointComparer : IEqualityComparer<Point>
{
    public bool Equals(Point p1, Point p2)
    {
        return p1.x==p2.x && p1.y == p2.y;
    }
    public int GetHashCode(Point p1)
    {
        return p1.x*p2.x;//bla bla
    }
}

goodPoints = rawPoints.Distinct(new PointComparer()).ToList();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM