如何在二维数组的范围内使用 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()的主要内容,如果未能解决你的问题,请参考以下文章