6

Given an array of integers.

For example:

[1,2,2,2,5,7]

I want to output any groups of consecutive identical numbers with their sum.

The output should be:

[1,6,5,7]

Any thoughts on how to do this?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
ArnoldB
  • 165
  • 3
  • 10

4 Answers4

3

You can use Array.prototype.reduce() with a temporary object.

var array = [1, 2, 2, 2, 5, 7],
    result = array.reduce(function (r, a) {
        if (r.last === a) {
            r.array[r.array.length - 1] += a;
        } else {
            r.array.push(a);
            r.last = a;
        }
        return r;
    }, { array: [], last: null }).array;

document.write('<pre>' + JSON.stringify(result,0,4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
3

I solved it this way.

const sumConsecutives = (s) => {
  let result = [], temp = 0;
  for(let i = 0; i<s.length; i++) {
    if(s[i] === s[i+1]){
      temp += s[i];
    } else if(s[i] !== s[i+1]){
      result.push(temp + s[i]);
      temp = 0;
    }
  }
  return result;
};
0

We could solve this using iteration. The code would look something like this

var numbers = [1, 2, 2, 2, 5, 7];
var newNumbers = [];

for (var i = 0; i < numbers.length; i++) {
    numbers = numbers.filter(function(num) {
        return num;
    });

Here we are removing elements that are undefined which will be deleted, so we don't repeat groups.

    var number = numbers[i];
    var nextUnique = numbers.find(function(num) {
        return num != number
    });
    var numbersToFind = numbers.indexOf(nextUnique) - i;

Above, we are searching for the number of numbers in a repeated group.

    if (numbersToFind > 0) {
        var numbersGroup = numbers.slice(i, i + numbersToFind + 1);
        var sumNumbers = numbersGroup.reduce(function(num1, num2) {
            return num1 + num2;
        });
        newNumbers.push(sumNumbers);
        delete numbers[i];
    }

We use the reduce function to sum up the numbers that are identical. We will then delete the original number to prevent duplicates in our newNumbers array.

    else {
        newNumbers.push(numbers[i]);
   }
}

Otherwise, the new number will simply be the number at the index.

alert(newNumbers);

Browser Compatibility

It should be noted that the array.prototype.find function is an experimental technology and is not yet available on Internet Explorer or Opera.

Richard Hamilton
  • 25,478
  • 10
  • 60
  • 87
  • just a short question to this: `numbers = numbers.filter(function(num) { return num; });` why? this filters only values who are truthy, but for what? – Nina Scholz Jan 26 '16 at 20:02
  • As I explained, in order to avoid iterating over repeated elements, after I've performed a reduce operation, I will delete the element at that index. This makes the element appear as `undefined`. That's why we need to filter for true elements at the start of every iteration – Richard Hamilton Jan 26 '16 at 20:05
  • 1
    maybe you should state, that `numbers.find` is not available on all user agents ... – Nina Scholz Jan 26 '16 at 21:14
0

If you use lodash and want a functional variant, you could also do:

_.chain([1,2,2,2,5,7]).groupBy(_.identity).map(_.sum).value()
i-blis
  • 3,149
  • 24
  • 31