3

I'd like to combine identical elements in an array, into a single term with how many times the value appears

function combineArrayElements(arr) {
  return arr.map((e, i, ar) => {
    if (e === ar[i + 1] || (e[0] && e[0] === ar[i + 1])) {
      return [e, e[1] + 1]
    }
    return e;
  })
}

Some example input and output:

// input  [3, 2, 2, 5, 1, 1, 7, 1]
// output [3,[2,2],5,[1,2],7,1]

// input  [1, 1, 1, 2, 1]
// output [[1,3], 2, 1]
3
  • I dont know how do this with reduce Commented May 12, 2020 at 16:00
  • 1
    Not quite clear about the question! Want to group similar items? Commented May 12, 2020 at 16:01
  • 1
    yes, I want to group elements if they are near Commented May 12, 2020 at 16:03

4 Answers 4

3

You could reduce the array and if the value is equal the last value, take an array and increment the counter.

const
    getGrouped = array => array.reduce((r, v, i, { [i - 1]: last }) => {
        if (v === last) {
            if (!Array.isArray(r[r.length - 1])) r[r.length - 1] = [r[r.length - 1], 1];
            r[r.length - 1][1]++;
        } else {
            r.push(v);
        }
        return r;
    }, []);

console.log(getGrouped([3, 2, 2, 5, 1, 1, 1, 7, 1]));
console.log(getGrouped([2, 2, 2, 3]));

Sign up to request clarification or add additional context in comments.

7 Comments

Even if it works, it looks like ancient Aramaic text. Code should be immediately understandable especially if it's few lines long. There is no point in sharing solutions like this one in a knowledge sharing platform. This is just entropy.
this work not fine. if array = [2,2,2,3] after reduce we get = [2,[2,2],3] First element ignored
@AlexLatro sorry, should work now. the counter was wrong initialized.
Very cool - hadn't seen { [i - 1]: last } used like that before - handy way to grab previous element
@Mr.X, [i - 1] is a computed property and because it's a number, it can not be used as variable, so it is renamed to last. the destruturing takes place with an array and the result is a variable last with the element of the last index.
|
1

Thank, Joseph Cho - answer is:

function splitCounts(arr) {
  let res = [];
  let count = 1;

  for (let i=0; i<arr.length; i++) {
    if (arr[i] === arr[i+1]) {
      count++;
    } else {
      res.push([arr[i], count]);
      count = 1;
    }
  }

  return res;
}

// [[3,1],[2,2],[5,1],[1,2],[7,1],[1,1]]
console.log(splitCounts([3,2,2,5,1,1,7,1]));

Comments

0

Refactored Nina Scholz's answer with longer variable names, comments, and slightly different control of flow:

const combineAdjacentElements = array => array.reduce((acc, val, i) => {
    // if cur is different from prev value, add raw number
    if (val !== array[i - 1]) {
      acc.push(val)
      return acc
    }

    // if first repetition, replace val with grouped array
    if (typeof acc.at(-1) === 'number') {
        acc[acc.length - 1] = [val, 2];
        return acc
    }

    // if multiple repetition, increment counter in grouped array
    acc.at(-1)[1]++;
    return acc;
}, []);


const output = combineAdjacentElements([3, 2, 2, 2, 5, 1, 1, 7, 1])

console.log(JSON.stringify(output, null, 0))
// [3,[2,3],5,[1,2],7,1]

Further Reading

Comments

-2

Just use Array.reduce() to get that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.