How to reduce a string expression like "20hc+2a+2hc+9op" to "22hc+2a+9op"

I think for readability, just use an indexOf pair conversion, and build a hash. For example:

const getPair = str => {
  const numbers = '0123456789'
  for (var i = 0; i < str.length; i++) {
    if(numbers.indexOf(str.charAt(i)) < 0){ break }
  }
  return [str.slice(i), i === 0 ? 1 : parseInt(str.slice(0, i))]
}
  
//const eq = '20hc+2a+2hc+9op+330o+10op'
const eq = 'a+2ab+3b+4c+5bc'

const hash = eq.split('+')
               .map(getPair)
               .reduce((r, [key, val]) => {
                 r[key] = r[key] ? r[key] + val : val
                 return r
               }, {})

const result = Object.entries(hash).map(([key, val]) => `${val}${key}`).join('+')

console.log(result)


I will do this in two steps. The first step generates an object with the keys (alphabet letters) and the totals (sum of numbers) for each key. For this, we use String::split() and Array::reduce() in that order. An example of the generated object will be like:

{"hc": 22, "op": 19, ...}

The second step just formats the previous generated object to the desired output string. For this one we use Object.entries(), Array::map() and finally Array::join().

const input = "a+20hc+2a+2hc+9op+330o+10op";

// First, get keys and sum their total.

let res = input.split("+")
    .reduce((acc, curr) =>
    {
        let [match, val, key] = curr.match(/(\d*)(\w*)/);
        val = +val || 1;
        acc[key] = acc[key] ? acc[key] + val : val;
        return acc;
    }, {});

console.log(res);

// Now, format to the output string.

res = Object.entries(res).map(([x, y]) => y + x).join("+");
console.log(res);

However, you should note that the previous approach won't work if you have subtractions, but some minor changes can do the work:

const input = "-4a+20hc+2a+2hc+9op+330o+10op-340o";

// First, get keys and sum their total.

let res = input.split(/\+|(?=-)/)
    .reduce((acc, curr) =>
    {
        let [match, val, key] = curr.match(/(-*\d*)(\w*)/);
        val = +val || 1;
        acc[key] = acc[key] ? acc[key] + val : val;
        return acc;
    }, {});

console.log(res);

// Now, format to the output string.

res = Object.entries(res)
    .map(([x, y]) => y + x)
    .join("+")
    .replace(/\+-/, "-");

console.log(res);