O ponto chave aqui é encontrar uma forma de lidar com os algarismos separadamente sem deixar de lidar com suas notações em conjunto, ou seja, de soma e subtração. Uma forma que pode usar para alcançar isso é dividindo os algarismos em arrays, pois assim será mais fácil manipulá-los, além de mantermos a ordem dos algarismos.
Podemos começar separando os algarismo através de um .split(), afinal precisamos deles separados para poder manipulá-los melhor.
Uma vez separados, podemos iterar sobre eles e converter seus valores de forma básica usando a tabela romano-arábico, e o .map() é perfeito para essa tarefa. Dentro dele um switch pode retornar os valores corretos de forma simples.
Agora que temos um array com vários valores inteiros, basta encontrarmos uma forma de aplicar as regras da notação padrão e subtrativa nos elementos. O .reduce() seria uma forma possível de ir somando/subtraindo os elementos, no entanto os valores estão começando do maior para o menor (esquerda para direita na ordem do array). Poderíamos inverter o array antes de aplicar o .reduce() mas o javascript nos fornece uma forma ainda mais elegante de fazer isso através do método .reduceRight(). Ele faz exatamente o que precisamos.
Por fim, vamos conseguir utilizar todas as capacidades do método ao passar 4 argumentos, o valor acumulado, o elemento atual, o índice atual e o array sobre o qual estamos iterando. Com isso conseguiremos realizar o procedimento de somar ou subtrair os valores de acordo com a notação romana:
function romanNumeral(str) { const numeralsArray = str.split('')
const decimalsArray = numeralsArray.map(numeral => {
switch (numeral) {
case 'I':
return 1
case 'V':
return 5
case 'X':
return 10
case 'L':
return 50
case 'C':
return 100
case 'D':
return 500
case 'M':
return 1000
default:
return 0
}
})
return decimalsArray.reduceRight((accum, current, index, array) => {
if (current < array[index + 1]) {
return accum - current
} else {
return accum + current
}
}, 0)
}