【问题标题】:C# Fastest way to find the index of item in a listC#在列表中查找项目索引的最快方法
【发布时间】:2013-06-07 15:36:23
【问题描述】:

我想知道在列表中查找项目索引的最快方法是什么。我想知道的原因是因为我正在制作 XNA 渲染,但是当我只使用顶点缓冲区时,我开始在较大的模型上出现内存不足的异常,所以我现在已经实现了一个索引缓冲区系统。我的问题是我现在必须连续扫描一个包含我所有 Vector3 的列表,以查找我想要放置在我的索引缓冲区中的那个的索引。我目前正在扫描这样的索引:

        for (int i = 1; i < circleVect.Length; i++)
        {
            indices.Add(vertices.FindIndex(v3 => v3 == circleVect[i]));
            indices.Add(vertices.FindIndex(v3 => v3 == circleVect[i - 1]));
            indices.Add(vertices.FindIndex(v3 => v3 == middle));
        }

这很好用,只是它相当慢。计算一个圆柱体几乎需要 1 秒,而我的大型模型中有超过 70 000 个圆柱体。因此,我在加载较大的模型时看到加载屏幕超过 20 分钟,但仍未完成。不幸的是,这根本是不可接受的。如果我尝试加载较小的模型,则需要 5 分钟以上,而未索引的加载器只需要一秒钟左右。

我完全没有接受过 C# 方面的正式培训,甚至没有接受过 XNA 方面的培训,所以我知道这可能是一种非常低效的计算索引的方法,因此如果你们中的任何人能帮助我创建一个更高效的导入器,我将不胜感激。

PS。如有必要,我可以将列表更改为数组,但这将是最后的选择,因为它可能会给系统内存带来压力(导致异常),并且对我来说意味着相当多的编码。

【问题讨论】:

  • 如果顶点是排序的,那么最快的方法是使用二分查找。在列表和数组之间进行更改不会改变任何内容(除非您使用的是链表)。你应该发布你想要完成的事情,而不是“我怎样才能让它更快”,因为我认为你不能比你现在拥有的更快,但是你现在拥有的并不理想,你可能应该查看其他数据结构。
  • 您到底想知道什么?我基本上是从包含许多代表圆柱体的线段的格式中读取的。然后我在机器人末端计算一个四边形(现在)和四个四边形来连接它们。将两个正方形的顶点及其中心添加到列表中,然后通过确定向量 3、搜索其索引并将其添加到列表中来计算其余部分,如上所示。
  • 您是否尝试过使用 IndexOf 而不是 FindIndex?为每个查找传递一个 lambda 肯定会产生开销。不是说这就是答案,但我认为这可能会有所帮助。
  • 我不太确定如何为我的目的实现 IndexOf,你能帮忙吗?
  • vertices.IndexOf (circleVert [i])

标签: c# list xna indexing vertex-buffer


【解决方案1】:

在您的代码中,对于每个 FindIndex 行,您将遍历顶点 3 次。而是使用一个 for 循环并遍历并一次性检查所有三个条件。

【讨论】:

  • 这听起来确实是个好主意,但你能不能给我解释一下如何做到这一点或者可能是一个例子?
【解决方案2】:

您的主要性能杀手是在需要 70 000 次操作的 70 000 项列表中进行搜索。 这比在列表中搜索要快得多。

 Dictionary<int, Vertice> vertices = new Dictionary<int, Vertice>();

            for (int i = 1; i < vertices.Length; i++)
            {
                if (vertices.ContainsKey(vertices[i]))
                {
                    indices.Add(vertices[i]);
                }
                if (vertices.ContainsKey(vertices[i - 1]))
                {
                    indices.Add(vertices[i - 1]);
                }
                if (vertices.ContainsKey(vertices[middle]))
                {
                    indices.Add(vertices[middle]);
                }
            }

编辑:如果在列表中搜索需要 2 秒,在字典中搜索将需要 00:00:02 秒

【讨论】:

  • 符号 00:00:02 对我来说意味着 2 秒,所以我不知道 00:00:02 seconds 应该是什么意思。
  • 表示会非常快
  • 这对我没有帮助,因为似乎在“ContainsKey(...)”中我必须输入代表索引的 int 键,如果我已经以某种方式知道,那么这将是不必要的...
  • 给我们更多关于你的顶点的细节我不知道你需要什么数据结构
  • 顶点是 XNA 框架中的 Vector3 类型
【解决方案3】:
for (int i = 1; i < circleVect.Length; i++)
{
    for (int j = 0; j < vertices.Count; j++)
    {
        var v3 = vertices[j]; 
        if (v3 == circleVect[i] || v3 == circleVect[i - 1] || v3 == middle)
            indices.Add(j);
    }
}

您可能需要考虑添加逻辑以在找到所有三个索引后停止检查内部循环。

【讨论】:

  • vertices 是一个列表,而不是一个数组,所以我认为您应该将 vertices.Length 更改为 vertices.Count
【解决方案4】:

感谢所有答案,但没有一个真正起作用,而且看起来确实比我所拥有的更快。我最终不得不创建一个结构,我可以在其中根据给定的参考点计算所需的列表索引。

【讨论】:

    猜你喜欢
    • 2016-06-09
    • 2011-01-05
    • 2017-12-18
    • 1970-01-01
    • 2019-05-28
    • 1970-01-01
    • 2021-07-17
    • 2016-01-25
    • 2014-10-13
    相关资源
    最近更新 更多