[英]Recursion - Sum Nested Array
I'm trying to sum a nested array [1,2,[3,4],[],[5]]
without using loops but I don't see what's wrong with what I have so far.我试图在不使用循环的情况下对嵌套数组[1,2,[3,4],[],[5]]
求和[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;
}
try with尝试
function sumItems(array) {
let sum = 0;
array.forEach((item) => {
if(Array.isArray(item)) {
sum += sumItems(item);
} else {
sum += item;
}
})
return sum;
}
recursion is a functional heritage递归是一种功能遗产
Recursion is a concept that comes from functional style.递归是一个来自函数式风格的概念。 Mixing it with imperative style is a source of much pain and confusion for new programmers.将它与命令式风格混合在一起会给新程序员带来很多痛苦和困惑。
To design a recursive function , we identify the base and inductive case(s).为了设计递归函数,我们确定基本情况和归纳情况。
item
is Empty
.即, item
是Empty
。 return 0
返回0
item
.即,必须至少有item
。 if the item is a list, return its sum plus the sum of the rest
of the items如果项目是列表,则返回其总和加上rest
项目的总和item
that is not an array.归纳案例 2 - 至少有item
不是数组。 return this item plus the sum of the rest
of the items返回此项目加上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 )
As a result of this implementation, all pain and suffering are removed from the program.作为这种实施的结果,所有的痛苦和痛苦都从程序中消除了。 We do not concern ourselves with local state variables, variable reassignment, or side effects like forEach
and not using the return value of a function call.我们不关心局部状态变量、变量重新分配或副作用,如forEach
和不使用函数调用的返回值。
recursion caution递归注意
And a tail-recursive version which can be made stack-safe .还有一个可以使堆栈安全的尾递归版本。 Here, we add a parameter cont
to represent our continuation which effectively allows us sequence the order of +
operations without growing the stack – changes in bold在这里,我们添加了一个参数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))
Usage is identitcal用法相同
console.log
( sumDeep ([ [ 1, 2 ], [ 3, 4 ], [ 5, [ 6, [] ] ] ]) // 21
, sumDeep ([ 1, 2, 3, 4, 5, 6 ]) // 21
, sumDeep ([]) // 0
, sumDeep () // 0
)
performance enhancement性能提升
As @גלעד ברקן points out, array destructuring syntax used above (eg ...rest
) create copies of the input array.正如@גלעד ברקן 指出的那样,上面使用的数组解构语法(例如...rest
)会创建输入数组的副本。 As demonstrated in his/her answer, an index parameter can be used which will avoid creating copies.如他/她的回答所示,可以使用索引参数来避免创建副本。 This variation shows how the index technique can also be used in a tail-recursive way此变体显示了索引技术也可以以尾递归方式使用
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 )
Here's a version without using loops:这是一个不使用循环的版本:
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));
You could define a callback for using with Array#reduce
, which check if an item is an array and uses this function again for that array.您可以定义一个用于与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));
You may do as follows;您可以按照以下方式进行;
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,[]]));
The function argument designation [a,…as]
means that when the function is fed with a nested array like [1,2,3,[4,[5,[6]]],7,[]]
then a
is assigned to the head which is 1
and as
is assigned to the tail of the initial array which is [2,3,[4,[5,[6]]],7,[]]
.函数参数指定[a,…as]
意味着当函数被提供一个像[1,2,3,[4,[5,[6]]],7,[]]
这样a
嵌套数组时[1,2,3,[4,[5,[6]]],7,[]]
a
被赋值到头部是1
和as
分配给初始阵列的尾部,其是[2,3,[4,[5,[6]]],7,[]]
The rest should be easy to understand.其余的应该很容易理解。
function arraySum (array) {
if (array.length > 0) {
return arraySum(array[0]) + arraySum(array.slice(1));
}
if (array.length === 0) {
return 0;
} else {
return array;
}
};
This is similar to some of the other solutions but might be easier for some to read:这类似于其他一些解决方案,但对于某些人来说可能更容易阅读:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.