【问题标题】:swift more efficient way to search array for match of different types快速更有效地搜索数组以匹配不同类型的方法
【发布时间】:2017-09-19 13:57:20
【问题描述】:

我正在使用 Swift 3 在一个数组中找到一个 GKGraphNode,该数组的 x,y 位置与目标 x,y 位置匹配。下面是节点的初始化。您可以看到每个节点都有一个名为 gridPosition 的 vector_int2 坐标。我创建了一个由这些节点组成的数组来匹配我的地图的六边形网格。

class HexGraphNode : GKGraphNode {
var gridPosition: vector_int2!

required init(gridPosition: vector_int2) {
    super.init()

    self.gridPosition = gridPosition

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}

我需要能够搜索这个数组来找到占据某个特定网格坐标的节点。我正在使用下面的功能。当地图很小(例如 500 个节点以下)时,此功能可以正常工作。但是,随着数组的增长,程序会减慢到无法接受的程度。我需要一种更有效的方法来搜索数组并找到匹配的节点,而不是每次都从索引零开始。我一直在寻找其他帖子,但他们似乎总是比较相同类型的对象。在这种情况下,我需要将对象的属性(node.position)与不同的类型(vector_int2,其中包含一个 x,y 整数)进行比较。

func node(atGridPosition position: vector_int2) -> NodeType {

    var result: NodeType!

    for node in self.nodes as! [NodeType] {

        if node.gridPosition.x == position.x && node.gridPosition.y == position.y {
            result = node

            break
        }
    }

    return result
}

任何帮助将不胜感激。

【问题讨论】:

  • 在阵列上尝试first(whereindex(of),这很可能比循环快得多。顺便说一句:为什么gridPosition 隐式展开是可选的? 永远不要将变量声明为在 init 方法中初始化的隐式解包可选。去掉感叹号。如果在节点数组中找不到该位置,您的 node(atGridPosition 函数将可靠地崩溃。
  • @vadian filter 会慢得多,因为它总是会扫描整个数组,而不是在第一次匹配时停止。而index(of:) 需要正确实现Equatable 协议。
  • 我的错,我的意思是first(where)

标签: arrays swift algorithm search


【解决方案1】:

如果您的节点的网格位置没有动态变化,您可以保留一个节点字典而不是(或除此之外)您的数组。如果您的网格有固定(或最大)宽度或高度,则 x,y 坐标可以转换为单个整数值以用作字典中的键。否则,您可以使用两级字典。

然后访问节点将是 O(1) 操作而不是 O(n/2)。

【讨论】:

  • 使用 for 循环在我的 iPhone 6 上创建地图的原始加载时间为 15 秒。切换到 first(where) 方法将时间缩短到 5 秒。使用字典仅需 0.9 秒。这对于一次性设置来说已经足够了。感谢所有的大力帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-29
  • 2016-02-21
  • 2020-06-30
  • 2011-06-06
相关资源
最近更新 更多