最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Sum of Parts of An Array - JavaScript - Stack Overflow

programmeradmin3浏览0评论

Trying to solve this challenge on codewars. According to the challenge, the parts of array:

ls = [0, 1, 3, 6, 10]

Are

ls = [0, 1, 3, 6, 10]
ls = [1, 3, 6, 10]
ls = [3, 6, 10]
ls = [6, 10]
ls = [10]
ls = []

And we need to return an array with the sums of those parts.

So my code is as follows:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

console.log(partsSums([0, 1, 3, 6, 10]));

Trying to solve this challenge on codewars. According to the challenge, the parts of array:

ls = [0, 1, 3, 6, 10]

Are

ls = [0, 1, 3, 6, 10]
ls = [1, 3, 6, 10]
ls = [3, 6, 10]
ls = [6, 10]
ls = [10]
ls = []

And we need to return an array with the sums of those parts.

So my code is as follows:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

console.log(partsSums([0, 1, 3, 6, 10]));

The issue is that it wants us to add the last sum 0 when the array is empty. So we should be getting:

[ 20, 20, 19, 16, 10, 0 ]

Instead of

[ 20, 20, 19, 16, 10]

So I tried this:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
arrayOfSums.push(0);
return arrayOfSums;
}
console.log(partsSums([0, 1, 3, 6, 10]));

And this:

function partsSums(ls) {
  ls.push(0);
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

But these caused execution time-out errors on Codewars:

Execution Timed Out (12000 ms)

So I also tried:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > -1) {
    let sum = ls.reduce((a, b) => a + b);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

But now this causes a TypeError:

TypeError: Reduce of empty array with no initial value

I am not understanding the concept of how to get 0 into the array when all of the values have been shifted out. The challenge seems to want 0 as the final "sum" of the array, even when the array is empty. But you cannot reduce an empty array - what else can I do here?

EDIT: Tried adding initial value to the reduce method:

function partsSums(ls) {
  let arrayOfSums = []; 
  while(ls.length > 0) {
    let sum = ls.reduce((a, b) => a + b, 0);
    arrayOfSums.push(sum);
    ls.shift();
  }
return arrayOfSums;
}

Unfortunately this still fails the basic test :

expected [] to deeply equal [ 0 ]

Share Improve this question edited Jun 24, 2019 at 15:16 HappyHands31 asked Jun 24, 2019 at 14:57 HappyHands31HappyHands31 4,10119 gold badges65 silver badges117 bronze badges 14
  • 1 I have tried to solve it myself. I don't know what else to try. I am not understanding the concept of how to add the sum of an empty array to the final array. Because you can't use reduce on an empty array. Any other ideas? – HappyHands31 Commented Jun 24, 2019 at 15:01
  • Cant you just push 0 after the loop? – Kobe Commented Jun 24, 2019 at 15:04
  • 2 This: But you cannot reduce an empty array - that is not what that error message (TypeError: Reduce of empty array with no initial value) says. In fact, it is very specific: Please re-read the documentation for reduce: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - and then reread the error message. – Randy Casburn Commented Jun 24, 2019 at 15:05
  • 1 @RandyCasburn "If no initialValue is supplied, the first element in the array will be used. Calling reduce() on an empty array without an initialValue will throw a TypeError." So perhaps reduce is not the best method to find the sum of the array. – HappyHands31 Commented Jun 24, 2019 at 15:08
  • 1 BINGO! But consider the iterator point too. – Randy Casburn Commented Jun 24, 2019 at 15:11
 |  Show 9 more comments

6 Answers 6

Reset to default 12

There is no reason to compute the sum over and over. On a long array this will be very inefficient ( O(n²) ) and might explain your timeout errors. Compute the sum at the beginning and then subtract each element from it in a loop.

ls = [0, 1, 3, 6, 10]

function partsSums(ls) {
    let sum = ls.reduce((sum, n) => sum + n, 0)
    res  = [sum]
    for (let i = 1; i <= ls.length; i++){
        sum -= ls[i-1]
        res.push(sum )
    }
    return res
}
console.log(partsSums(ls))

Another solution that passed all of the tests:

function partsSums(ls) {
    let result = [0],
      l = ls.length - 1;
      
    for (let i = l; i >= 0; i--) {
        result.push(ls[i] + result[ l - i]);
    }
    return result.reverse();
}


console.log(partsSums([]));
console.log(partsSums([0, 1, 3, 6, 10])); 
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));

You could use for loop with slice and when i == 0 you can slice len + 1 which is going to return you empty array and sum will be 0.

function partsSums(arr) {
  const res = [], len = arr.length
  for (let i = len; i > -1; i--) {
    res.push(arr.slice(-i || len + 1).reduce((a, n) => a + n, 0))
  }
  return res;
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));

You can also use two double reduce and if there is no next element push zero.

function partsSums(arr) {
  const sum = arr => arr.reduce((r, e) => r + e, 0);
  return arr.reduce((r, e, i, a) => {
    const res = sum(a.slice(i, a.length));
    return r.concat(!a[i + 1] ? [res, 0] : res)
  }, [])
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));

try this with recursion :

function partsSums(ls) {
  let sum = ls.reduce((a, b) => a + b, 0);
  return  ls.length > 0 ? [sum].concat(partsSums(ls.slice(1))) : [0];
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));

Here's one thing you could do

function partsSums(ls) {
  if(!ls.length) return [0];
  let prevTotal = ls.reduce((a,b) => a + b);
  return [prevTotal, ...ls.map(val => prevTotal -= val)]
}

console.log(partsSums([0, 1, 3, 6, 10]));

You could iterate from the end and take this value plus the last inserted value of the result set.

This approach works with a single loop and without calculating the maximum sum in advance.

function partsSums(ls) {
  var result = [0],
      i = ls.length;
      
  while (i--) {
      result.unshift(ls[i] + result[0]);
  }
  return result;
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

With push and reverse.

function partsSums(ls) {
  var result = [0],
      l = 0,
      i = ls.length;
      
  while (i--) result.push(l += ls[i]);
  return result.reverse();
}

console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

发布评论

评论列表(0)

  1. 暂无评论