如何在二维数组的范围内使用 flatMap() 和 reduce()

How to use flatMap() and reduce() on a range of a 2d array

我有一个二维数组,我想使用类似于 flatMap 的东西,并与每个二维的范围一起减少。在我的示例中,我想在每行 0 到 2 中添加从位置 1 到 3 的每个数字。

目前我的代码看起来类似于以下内容并且确实有效。

let array = [
     [3,6,8,4],
     [3,7,4,6],
     [2,4,5,7],
     [5,3,7,4]
]

let row = 1
let col = 2
var reducedValue = 0        
        
(row-1...row+1).forEach {
     reducedValue = array[[=10=]][col-1...col+1].compactMap { [=10=] }.reduce(reducedValue, +)
}

预期输出为:

51
//6 + 8 + 4 + 7 + 4 + 6 + 4 + 5 + 7

但是我想知道是否有类似于这个的解决方案:

reducedValue = array[row-1...row+1][col-1...col+1].compactMap { [=12=] }.reduce(0, +)

或者甚至没有类似这样的 compactMap:

reducedValue = array[row-1...row+1][col-1...col+1].reduce(0, +)

您可以将数组的数组展平,然后 reduce。例如:

let total = array[row-1...row+1]
    .flatMap { [=10=][col-1...col+1] }
    .reduce(0, +)

产生:

51


如果您想避免构建扁平化数组的开销(这无关紧要,除非处理非常大的子数组,即数百万个值),您可以延迟执行计算:

let total = array[row-1...row+1]
    .lazy
    .flatMap { [=11=][col-1...col+1] }
    .reduce(0, +)

另一个选项,它添加所选行和列的值而不创建中间数组:

let value = array[row-1...row+1].reduce(0, { [=10=] + [col-1...col+1].reduce(0, +) })
print(value) // 51

外部 reduce() 遍历选定的行并为每一行添加选定列中的值的总和,这些值是在内部 reduce().[=13 中计算的=]

虽然函数式方法会给您最简洁的代码

let result = array[row-1...row+1].reduce(into: 0) { [=10=] += [col-1...col+1].reduce(into: 0, +=) }

,经典的命令式代码不容忽视:

var result = 0
for i in row-1...row+1 {
    for j in col-1...col+1 {
        result += array[i][j]
    }
}

命令式方法虽然更冗长而且不是 100% Swift 惯用语(当 let 替代存在时使用 var),但在这个特定的上下文中更具可读性,处理数学概念。