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

Posted

技术标签:

【中文标题】如何在二维数组的范围内使用 flatMap() 和 reduce()【英文标题】:How to use flatMap() and reduce() on a range of a 2d array 【发布时间】:2021-02-11 04:48:09 【问题描述】:

我有一个 2d 数组,我想使用类似于 flatMap 的东西,并将 reduce 与每个二维的范围一起使用。在我的示例中,我想在 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[$0][col-1...col+1].compactMap  $0 .reduce(reducedValue, +)

预期的输出是:

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

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

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

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

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

【问题讨论】:

请提供输入(您拥有的)和所需的输出。 我更新了我的问题。谢谢! :) 【参考方案1】:

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

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

产生:

51


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

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

【讨论】:

【参考方案2】:

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

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

外部reduce() 迭代选定的行,并为每一行添加选定列中的值的总和,这些值在内部reduce() 中计算。

【讨论】:

【参考方案3】:

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

let result = array[row-1...row+1].reduce(into: 0)  $0 += $1[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),但在处理数学概念的特定上下文中更具可读性。

【讨论】:

我也喜欢命令式代码的理解性和可读性。然而,我的原始代码已经嵌入到几乎两个类似的 for-in 循环中来迭代二维数组。并将每个值存储在一个新的二维数组中。这将意味着 4 个级别的 for-in 循环。 :) @MarcoBoerner,是的,4 级 for 循环一点都不好。您可能希望将该逻辑一分为二:计算 2d 数组,计算每个 2d 数组的总和,无论您采用何种总和计算方法(函数式或命令式)

以上是关于如何在二维数组的范围内使用 flatMap() 和 reduce()的主要内容,如果未能解决你的问题,请参考以下文章

在Excel C#范围内写入二维对象数组

LeetCode﹝前缀和ி﹞一维二维前缀和应用

HDU_4456_二维树状数组

Unity3d在屏幕范围内随机生成一个圆

如何将值设置为二维 Excel 范围?

swift 高级用法