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]

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

<!-- begin snippet: js hide: false console: true babel: false --> <!-- language: lang-js -->
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]
<!-- end snippet -->

Further Reading