Tengo una matriz de objetos y quiero agregar un elemento a un índice específico cuando un determinado atributo cambia en comparación con el anterior.
Tenemos:
const arr = [ { num: 1 }, { num: 1 }, { num: 1 }, { num: 3 }, { num: 3 }, { num: 4 }, { num: 5 }, ];quiero que se convierta
const arr = [ { separator:true } { num: 1 }, { num: 1 }, { num: 1 }, { separator:true } { num: 3 }, { num: 3 }, { separator:true } { num: 4 }, { separator:true } { num: 5 }, ];Hice esto:
const getIndexes = (myArr) => { let indexes = []; let previousValue = null; myArr.forEach((el, idx) => { if (el.num !== previousValue) { indexes.push(idx); previousValue = el.num; } }); return indexes; }; const insertSeparator = (arr) => { let result = arr; getIndexes(arr).forEach((position) => result.splice(position, 0, { separator: true })); return result };y devuelve:
[ { separator: true }, { num: 1 }, { num: 1 }, { separator: true }, { num: 1 }, { separator: true }, { separator: true }, { num: 3 }, { num: 3 }, { num: 4 }, { num: 5 } ]Tal vez por el "nuevo" tamaño del arreglo, porque cada vez es más grande y cambia de dimensión.
¿Cuál crees que es la mejor manera de resolver esto?
Propongo esta solución que consumiría solo una iteración con una reducción:
const arr = [{ num: 1 }, { num: 1 }, { num: 1 }, { num: 3 }, { num: 3 }, { num: 4 }, { num: 5 }, ]; let prev_value = arr[0]; const result = arr.reduce((acc, val) => { const insert = (val.num !== prev_value.num) ? [{ separator: true }, val] : [val]; prev_value = val; return acc.concat(insert) }, [{ separator: true }, ]) console.log(result)Ejecútelo a través .flatMap()
const result = arr.flatMap((obj, idx, arr) => {... .flatMap() es .map() y .flat() combinados, por lo que transforma el contenido de una copia de la matriz dada y elimina los corchetes [] . A continuación, devolvemos el primer objeto con un separador:
if (idx == 0) { // returns are wrapped in brackets because they'll be removed before being returned return [{separator: true}, obj]; }El siguiente paso es comparar el valor actual con el valor anterior:
obj.num == arr[idx - 1].num ? // current value vs previous value [arr[idx - 1]] : // if they are the same value return previous value [{separator: true}, obj]; /* if they are not the same then return that separator and current */ const arr = [ { num: 1 }, { num: 1 }, { num: 1 }, { num: 3 }, { num: 3 }, { num: 4 }, { num: 5 }, ]; const result = arr.flatMap((obj, idx, arr) => { if (idx == 0) { return [{ separator: true }, obj]; } return obj.num == arr[idx - 1].num ? [arr[idx - 1]] : [{ separator: true }, obj]; }); console.log(JSON.stringify(result, null, 2));Debe haber otras formas de hacerlo también. Pero con una simple modificación de su código se puede hacer. Solo necesita realizar un seguimiento del desplazamiento con una nueva variable, incrementándola en el ciclo:
const arr = [ { num: 1 }, { num: 1 }, { num: 1 }, { num: 3 }, { num: 3 }, { num: 4 }, { num: 5 }, ]; const getIndexes = (myArr) => { let indexes = []; let previousValue = null; myArr.forEach((el, idx) => { if (el.num !== previousValue) { indexes.push(idx); previousValue = el.num; } }); return indexes; }; const insertSeparator = (arr) => { let result = [...arr]; let offset = -1; getIndexes(arr).forEach((position) => { offset++; return result.splice(position+offset, 0, { separator: true }); }); return result }; console.log(insertSeparator(arr)); Nota: si desea comenzar con 0 , puede hacer el incremento en el .splice() : result.splice(position+(offset++),