我有一系列点,我们称之为rawPoints,其中包含重复项。实际上,几乎每个点都重复了2到6次。重复某处,而不是在连续的位置。我想删除重复项以获得一个新的集合,我称之为goodPoints。另外,我想知道从rawPoints到goodPoints的映射。换句话说,对于rawPoints中的每个点P,我想知道(唯一)索引i,使得goodPoints [i] = P.
我在C#编码,所以我想知道是否有任何.NET集合可以帮助解决这个问题。
我读过使用HashSet是删除重复项的好方法。但那不会给我映射。
一种可能的解决方案是" AddorFind(P)"我可以用来向goodPoints添加点P的函数。如果P还不是goodPoints的成员,那么AddorFind(P)将添加它。如果P已经是goodPoints的成员,则AddorFind(P)将返回索引i,使得goodPoints [i] = P.
是否存在类似的东西,或者是否有其他简单且合理的快速解决方案?
答案 0 :(得分:3)
虽然HashSet<Point>
无法在goodPoints
中找到唯一索引,但Dictionary<Point,int>
会。{/ p>
除了List<Point> goodPoints
之外,还要创建一个字典Dictionary<Point,int> mappings
,将点映射到goodPoints
列表中的索引。当您浏览rawPoints
数组时,请遵循以下算法:
rawPoints[i]
是否在mappings
。如果是,请继续下一步goodPoints
的当前长度添加到mappings
的{{1}},然后将rawPoints[i]
添加到rawPoints[i]
列表。假设您的gooodPoints
表示具有良好的哈希函数,并且它正确地覆盖Point
,则此算法会生成Equals
列表和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;
}
}
}
答案 2 :(得分:1)
您可以使用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));
}
答案 3 :(得分:0)
您可以创建一个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();