c# - 删除 List<object> 的重复对

标签 c# wpf list duplicates

问题

我在 3D WPF 库中使用简单的线条显示几何图形。在下一张图片中可以看到它的一个例子:

enter image description here

在其中您可以看到一组三角形和四边形。我绘制这个的方式是我提供一个 List<Point3D>我在其中放置了代表每个片段的成对点。

问题是有很多重复的边,我想避免这种情况,因为这种表示似乎对资源要求很高。

点列表是在每个 Element 上迭代生成的包含 N 个顶点。它不知道特定边是否共享。

<p0, p1, p1, p2, p2, p333, p333, p89, p89, p2, p2, p1 ...>

想法是删除重复的对(注意顺序可能不一样)。在上面的示例中,删除的对应该是最后一对 (p2, p1),因为它表示与第二对点 (p1, p2) 相同的边。可能有一对、两对或多对重复的点。

我需要尽快完成这个操作,性能是最重要的。

想法

在列表中添加点时,我可以临时存储其中的两个并检查列表是否已经包含它们,但这意味着每次我添加一个点时都要查看一个列表,这对我来说似乎不是一个好主意(列表将包含数千个点 5000-50000)。

我生成点列表的元素有几个具有唯一 ID 的节点,因此我认为可以通过创建 Dictionary 以某种方式使用它已订购 Tuple<Point3D, Point3D>然后删除重复项。

我还没有尝试过最后一个想法,因为我还不确定如何实现它,我想听听是否还有其他可以做的事情。

最佳答案

您可以使用HashSet 来存储所有的边。检查速度很快,边缘是否已经设置好。但是您应该覆盖 GetHashCodeEquals。我做了一个简单的例子。

class MyLine
{
    public MyPoint P1 { get; private set; }
    public MyPoint P2 { get; private set; }
    public MyLine(MyPoint p1, MyPoint p2)
    {
        P1 = p1;
        P2 = p2;
    }
    protected bool Equals(MyLine other)
    {
        return (Equals(P1, other.P1) && Equals(P2, other.P2)) || Equals(P1, other.P2) && Equals(P2, other.P1);
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((MyLine)obj);
    }
    public override int GetHashCode()
    {
        unchecked
        {
            return P1.GetHashCode() + P2.GetHashCode();
        }
    }
}
class MyPoint
{
    public string Id { get; private set; }
    public MyPoint(string id)
    {
        Id = id;
    }
    protected bool Equals(MyPoint other)
    {
        return string.Equals(Id, other.Id);
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((MyPoint)obj);
    }
    public override int GetHashCode()
    {
        return (Id != null ? Id.GetHashCode() : 0);
    }
}

那么你应该能够像这样添加每一行:

public static void Main(string[] args)
{
    HashSet<MyLine> lines = new HashSet<MyLine>();
    var line = new MyLine(new MyPoint("a"), new MyPoint("b"));
    lines.Add(line);
    line = new MyLine(new MyPoint("b"), new MyPoint("a"));
    lines.Add(line);
}

还有 GetHashCodeEquals 可以将所有行存储在 List 中,然后使用 Distinct 方法。

public static void Main(string[] args)
{
    List<MyLine> lines = new List<MyLine>();
    var line = new MyLine(new MyPoint("a"), new MyPoint("b"));
    lines.Add(line);
    line = new MyLine(new MyPoint("b"), new MyPoint("a"));
    lines.Add(line);
    lines = lines.Distinct().ToList();
}

关于c# - 删除 List<object> 的重复对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24848638/

相关文章:

c# - 从字符串末尾删除多个 char 类型

c# - 加速 LINQ to SQL 查询

c# - 如何以一种样式访问控件父级的属性

c++ - 关于 C++ 中的列表

Python:复制列表

Python 用逗号连接字符串列表,但有一些条件 - 代码重构

c# - 从也使用其中一些包的项目中引用使用 NuGet 包的程序集

c# - 我可以让 NugetRestore 在 azure devops (TFS) 上与 build.cake 一起工作吗

c# - WPF RichTextBox 底部的文本

.net - 我的图像很模糊!为什么 WPF 的 SnapsToDevicePixels 不起作用?