获取周围坐标的最短代码是啥?

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)]

实现相同(正确)结果的最短方法是什么?我在想mapfilterreduce等函数,但目前还没有找到合适的组合...

【问题讨论】:

【参考方案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】:

由于您只查找相邻位置并且似乎对 xy 没有限制,因此您可以保存一组 (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 坐标。

以上是关于获取周围坐标的最短代码是啥?的主要内容,如果未能解决你的问题,请参考以下文章

导致堆栈溢出的最短代码是啥? [关闭]

查看以获取条件复杂的最短日期

在 Python 3 中获取“OrderedDict”第一项的最短方法

在java中初始化字符串列表的最短方法是啥?

如何获取每个外键的最短日期记录的记录 ID?

获取所有记录,每个月的最短日期,但最新的时间