获取周围坐标的最短代码是啥?
Posted
技术标签:
【中文标题】获取周围坐标的最短代码是啥?【英文标题】:What is the shortest code to get surrounding coordinates?获取周围坐标的最短代码是什么? 【发布时间】:2017-05-25 12:39:58 【问题描述】:我不喜欢我对surroundingPositions
的以下实现来获取围绕特定位置的 x 和 y 坐标,因为在我看来,它对于简单的意图来说太长了,而且它有一个厄运金字塔结构。
struct Position: CustomStringConvertible
let x, y: Int
var surroundingPositions: [Position]
var surroundingPositions: [Position] = []
for x in (self.x - 1)...(self.x + 1)
for y in (self.y - 1)...(self.y + 1)
if !(x == self.x && y == self.y)
surroundingPositions.append(Position(x: x, y: y))
return surroundingPositions
var description: String
return "(\(x),\(y))"
用法:
let testPosition = Position(x: 1, y: 1)
print(testPosition.surroundingPositions)
// Output: [(0,0), (0,1), (0,2), (1,0), (1,2), (2,0), (2,1), (2,2)]
实现相同(正确)结果的最短方法是什么?我在想map
、filter
、reduce
等函数,但目前还没有找到合适的组合...
【问题讨论】:
【参考方案1】:好吧,您总是可以对其进行硬编码。在这里,我对增量进行了硬编码,并为每个增量创建了一个新的 Position
:
var surroundingPositionsHardcoded: [Position]
let deltas: [(Int, Int)] = [(-1, -1), (-1, 0), (-1, +1), (0, -1), (0, +1), (+1, -1), (+1, 0), (+1, +1)]
return deltas.map Position(x: x+$0.0, y: y+$0.1)
或者,您可以使用map
计算增量。这还有一个额外的好处,就是您可以增加周围的距离。
var surroundingPositionsComputed: [Position]
let deltas = (-1...1).map dx in (-1...1).map dy in (dx, dy)
.joined()
.filter $0.0 != 0 || $0.1 != 0
return deltas.map Position(x: x+$0.0, y: y+$0.1)
【讨论】:
特别是第二个解决方案是我正在寻找的。简短而优雅,谢谢! 我应该指出(对于未来可能的读者),如果邻域“半径”是一个常数(在本例中为:1
),则不应首选第二种方法。可能编译器会将deltas
计算优化为单个调用,但我建议将filter
调用放在deltas
实例化而不是return
调用上,因为(给定一个常量“半径”)对于给定位置实例的对周围位置的计算的每次调用,我们真的不想执行常量与常量的过滤。对于不同的半径,请选择 #2!
我赞同@dfri 所说的。实际上,我在创建增量时使用了过滤器,但将其放在第二行以缩短行数。我更新了应用 dfri 建议的帖子并添加了一些换行符。如果距离是(并且将是)一个常数,您当然可以继续并将其设为静态变量,就像 dfri 的答案一样。【参考方案2】:
由于您只查找相邻位置并且似乎对 x
或 y
没有限制,因此您可以保存一组 (x, y)
翻译,每个翻译将给定的 Position
映射到其 8 个不同的相邻位置之一那些。
struct Position: CustomStringConvertible
let x, y: Int
// order of resulting neighbouring positions, given a position P
// (1) (2) (3)
// (4) (P) (5)
// (6) (7) (8)
private static let surroundingPositionsTranslations: [(x: Int, y: Int)] = [
(-1, -1), (0, -1), (1, -1),
(-1, 0), (1, 0),
(-1, -1), (0, -1), (1, -1)]
var surroundingPositions: [Position]
return Position.surroundingPositionsTranslations
.map Position(x: x + $0.x, y: y + $0.y)
var description: String
return "(\(x),\(y))"
// Note that I've changed the order w.r.t. OP:s original code
// (modify the transfotmation above to modify the order)
let testPosition = Position(x: 1, y: 1)
print(testPosition.surroundingPositions)
// Output: [(0,0), (1,0), (2,0), (0,1), (2,1), (0,0), (1,0), (2,0)]
【讨论】:
这绝对是比我目前拥有的更好的解决方案。但是,我接受了另一个具有相同内容(硬编码)以及更灵活和优雅的解决方案(计算)的答案。不过还是谢谢你的回答! @BennoKress 很乐意为您提供帮助。是的,我注意到我们同时发布了一些相同的内容:) 只要确保更喜欢“硬编码”的内容,以防您没有不同的邻域半径(如您的示例:静态并设置为 @987654326 @),作为“计算”方法,对于恒定半径,在每次调用时将不必要地执行嵌套的map
、数组初始化等(可能由编译器优化),然后是不必要的filter
,只是为了过滤如果使用一组静态“硬编码”转换,我们可能已经忽略了单个 self
坐标。以上是关于获取周围坐标的最短代码是啥?的主要内容,如果未能解决你的问题,请参考以下文章