Dada la siguiente matriz:
const arr = [ {color: 'red'}, {color: 'red'}, {color: 'green'}, {color: 'blue'}, {color: 'blue'}, {color: 'red'}] ¿Cómo mapear a través de su elemento para crear una matriz de objetos extendidos con la propiedad colorIndex que funcionaría como un contador de cuántos elementos anteriores tienen la misma propiedad de color ?
el resultado sería una matriz siguiente:
[ {color: 'red', colorIndex: 0}, {color: 'red', colorIndex: 1}, {color: 'green', colorIndex: 0}, {color: 'blue', colorIndex: 0}, {color: 'blue', colorIndex: 1}, {color: 'red', colorIndex: 2} ]¿Hay alguna solución elegante para lograr eso?
Basado en el comentario de @FZs, estoy publicando una solución mucho más rápida (y más clara). Requiere muchas menos operaciones para completar y mucho menos "poder mental" (también conocido como carga cognitiva) para leerlo;)
const arr = [ { color: 'red' }, { color: 'red' }, { color: 'green' }, { color: 'blue' }, { color: 'blue' }, { color: 'red' } ] var countByColor = new Map(); console.log( arr.map(function mapArray(elem, index) { var color = elem.color; var count = countByColor.get(color) || 0; countByColor.set(color, count + 1); // add 1, so next time we spot the color it will get correct counter return { color, count } }) )Prueba de rendimiento antigua vs nueva: https://jsbench.me/7kkx5zffpm/2
Bueno, no estoy seguro de por qué preguntas y qué has intentado ya para resolver esto. Es difícil obtener una respuesta adecuada cuando no hay ningún contexto. Pero aquí está mi enfoque, tal vez aprendas un poco:
arr.map((elem, index) => { // we only care about values before current index, to see how many elements with given color were **before** var colors = arr.map((obj) => obj.color).splice(0, index + 1); return { ...elem, // using spread operator to get all properties of original object count: colors.reduce( (prev, curr) => (curr == elem.color ? prev + 1 : prev), -1 // starting from -1 to get 0-based counter ), }; })Véalo en stackblitz aquí: https://stackblitz.com/edit/js-bnru4m
Lea más sobre reducir : https://developer.mozilla.org/pl/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Lea más sobre el operador de propagación : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
Obtenga más información sobre cómo empalmar una matriz: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
Lea más sobre mapear una matriz: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
La primera solución que me viene a la mente no es elegante, pero funcionará. Lo mejor es trabajar con un objeto adicional.
const foundItems = {}; arr.map(item => { let foundItem = foundItems[item.color] ? foundItems[item.color]+ 1 : 0; foundItems[item.color] = founditem; return { ...item, colorIndex: foundItem, } })