我试图在不使用循环的情况下对嵌套数组[1,2,[3,4],[],[5]]
进行求和,但我不知道到目前为止我有什么错误。
function sumItems(array) {
let sum = 0;
array.forEach((item) => {
if(Array.isArray(item)) {
sumItems(item);
} else {
sum += item;
}
})
return sum;
}
答案 0 :(得分:3)
尝试
fetch
答案 1 :(得分:3)
递归是一种功能性传承
递归是一种来自功能风格的概念。将它与命令式风格混合是新程序员的痛苦和困惑的源泉。
To design a recursive function,我们确定了基础和归纳案例。
item
是Empty
。返回0
item
。如果该项目是列表,则返回其总和加上项目的rest
的总和item
不一个数组。返回此商品加上商品rest
的总和
const Empty =
Symbol ()
const sumDeep = ([ item = Empty, ...rest ] = []) =>
item === Empty
? 0
: Array.isArray (item)
? sumDeep (item) + sumDeep (rest)
: item + sumDeep (rest)
console.log
( sumDeep ([ [ 1, 2 ], [ 3, 4 ], [ 5, [ 6, [] ] ] ]) // 21
, sumDeep ([ 1, 2, 3, 4, 5, 6 ]) // 21
, sumDeep ([]) // 0
, sumDeep () // 0
)
由于这种实施,所有的痛苦都会从计划中消除。我们不关心本地状态变量,变量重新分配或副作用,如forEach
,也不使用函数调用的返回值。
递归警告
可以制作stack-safe的尾递归版本。在这里,我们添加一个参数cont
来表示我们的延续,这有效地允许我们按顺序排列+
操作而不增加堆栈 - 粗体
const identity = x => x const sumDeep = ([ item = Empty, ...rest ] = [], cont = identity) => item === Empty ? cont (0) : Array.isArray (item) ? sumDeep (item, a => sumDeep (rest, b => cont (a + b))) : sumDeep (rest, a => cont (item + a))
用法是标识
console.log
( sumDeep ([ [ 1, 2 ], [ 3, 4 ], [ 5, [ 6, [] ] ] ]) // 21
, sumDeep ([ 1, 2, 3, 4, 5, 6 ]) // 21
, sumDeep ([]) // 0
, sumDeep () // 0
)
效果提升
正如@גלעדברקן所指出的,上面使用的数组解构语法(例如...rest
)创建了输入数组的副本。如他/她的回答所示,可以使用索引参数,这将避免创建副本。此变体显示了索引技术如何也可以以尾递归的方式使用
const identity = x =>
x
const sumDeep = (items = [], i = 0, cont = identity) =>
i >= items.length
? cont (0)
: Array.isArray (items [i])
? sumDeep (items [i], 0, a =>
sumDeep (items, i + 1, b =>
cont (a + b)))
: sumDeep (items, i + 1, a =>
cont (items [i] + a))
console.log
( sumDeep ([ [ 1, 2 ], [ 3, 4 ], [ 5, [ 6, [] ] ] ]) // 21
, sumDeep ([ 1, 2, 3, 4, 5, 6 ]) // 21
, sumDeep ([]) // 0
, sumDeep () // 0
)
答案 2 :(得分:1)
这是一个不使用循环的版本:
function f(arr, i){
if (i == arr.length)
return 0;
if (Array.isArray(arr[i]))
return f(arr[i], 0) + f(arr, i + 1);
return arr[i] + f(arr, i + 1);
}
console.log(f([1,2,[3,4],[],[5]], 0));

答案 3 :(得分:0)
您可以定义一个与Array#reduce
一起使用的回调,它会检查一个项目是否为数组并再次对该数组使用此函数。
function add(s, v) {
return Array.isArray(v)
? v.reduce(add, s)
: s + v;
}
var array = [1, 2, [3, 4], [], [5]];
console.log(array.reduce(add, 0));

答案 4 :(得分:0)
您可以执行以下操作;
===
函数参数名称var sumNested = ([a,...as]) => (as.length && sumNested(as)) + (Array.isArray(a) ? sumNested(a) : a || 0);
console.log(sumNested([1,2,3,[4,[5,[6]]],7,[]]));
表示,当函数使用[a,…as]
之类的嵌套数组进行填充时,会将[1,2,3,[4,[5,[6]]],7,[]]
分配给a
和{{ 1}}被分配给初始数组1
的尾部。其余的应该很容易理解。
答案 5 :(得分:0)
function arraySum (array) {
if (array.length > 0) {
return arraySum(array[0]) + arraySum(array.slice(1));
}
if (array.length === 0) {
return 0;
} else {
return array;
}
};
答案 6 :(得分:0)
这与其他一些解决方案相似,但对于某些人来说可能更容易阅读:
function Sum(arr) {
if (!arr.length) return 0;
if (Array.isArray(arr[0])) return Sum(arr[0]) + Sum(arr.slice(1));
return arr[0] + Sum(arr.slice(1));
}
console.log(Sum([[1],2,[3,[4,[5,[6,[7,[8,9,10],11,[12]]]]]]])) // 78