Necesito contar la ocurrencia de valores específicos de una propiedad, agrupados por el valor de otra propiedad. Obtuve un código de trabajo, pero siento que se puede hacer de manera más genérica.
En primer lugar, tengo dos matrices constantes. Tengo una constante con los años y una constante con las diferentes posibilidades de los valores. Una tercera matriz (myArray) es una matriz formada por una llamada REST.
const properties = ["a", "b", "c"] const years = [2015, 2016, 2017, 2018] let myArray = [ { date: 2015, prop1: "a" }, { date: 2015, prop1: "b" }, { date: 2016, prop1: "b" }, { date: 2016, prop1: "a" }, { date: 2016, prop1: "c" }, { date: 2017, prop1: "b" }, { date: 2017, prop1: "a" }, { date: 2017, prop1: "a" }, { date: 2017, prop1: "b" }, { date: 2017, prop1: "b" }, { date: 2018, prop1: "c" }, { date: 2018, prop1: "b" }, ]
A continuación tengo mi función. Esto se parece a esto.
function doClick() { let countArray = []; let counta = 0; let countb = 0; let countc = 0; for (let i = 0; i < years.length; i++) { let currentYear = years[i] for (let x = 0; x < properties.length; x++) { let currentProperty = properties[x]; for (let z = 0; z < myArray.length; z++) { if (myArray[z].date === currentYear && myArray[z].prop1 === currentProperty) { switch (currentProperty) { case "a": counta++; break; case "b": countb++; break; case "c": countc++; break; } } } } let obj = { 'year': currentYear, 'a': counta, 'b': countb, 'c': countc } countArray.push(obj) counta = 0; countb = 0; countc = 0; } console.log(countArray) }
Esto registra una matriz que puedo usar.
0: {year: 2015, a: 1, b: 1, c: 0} 1: {year: 2016, a: 1, b: 1, c: 1} 2: {year: 2017, a: 2, b: 3, c: 0} 3: {year: 2018, a: 0, b: 1, c: 1}
Pero las propiedades de matriz constante son en la vida real mucho más grandes. Así que me gustaría deshacerme de los casos codificados en la declaración de cambio y los let counta, countb y countc y hacerlo más flexible.
Entonces, ¿alguien puede ayudarme a mejorar este fragmento de código?
¡Gracias!
Puede agrupar con un objeto y tomar prop1
como acceso a la propiedad para incrementar el conteo.
const properties = ["a", "b", "c"], years = [2015, 2016, 2017, 2018], data = [{ date: 2015, prop1: "a" }, { date: 2015, prop1: "b" }, { date: 2016, prop1: "b" }, { date: 2016, prop1: "a" }, { date: 2016, prop1: "c" }, { date: 2017, prop1: "b" }, { date: 2017, prop1: "a" }, { date: 2017, prop1: "a" }, { date: 2017, prop1: "b" }, { date: 2017, prop1: "b" }, { date: 2018, prop1: "c" }, { date: 2018, prop1: "b" }], empty = Object.fromEntries(properties.map(k => [k, 0])), result = Object.values(data.reduce( (r, { date, prop1 }) => { r[date][prop1]++; return r; }, Object.fromEntries(years.map(year => [year, { year, ...empty }]))) ); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
No es necesario definir 2 const. Puedes consultar mi demostración a continuación:
let myArray = [ { date: 2015, prop1: "a" }, { date: 2015, prop1: "b" }, { date: 2016, prop1: "b" }, { date: 2016, prop1: "a" }, { date: 2016, prop1: "c" }, { date: 2017, prop1: "b" }, { date: 2017, prop1: "a" }, { date: 2017, prop1: "a" }, { date: 2017, prop1: "b" }, { date: 2017, prop1: "b" }, { date: 2018, prop1: "c" }, { date: 2018, prop1: "b" }, ]; var result = []; myArray.forEach(item => { var existResult = result.find(e => e.year == item.date); if (!existResult) { let newItem = {}; newItem['year'] = item.date; newItem['a'] = 0; newItem['b'] = 0; newItem['c'] = 0; newItem[item.prop1]++; result.push(newItem); } else { existResult[item.prop1]++; } }); console.log(result);
Puede usar reduce para esto y usar los años como claves en un objeto.
De esta manera, no le importa qué accesorios provienen de la API. Solo necesita verificar si existen cuando los llame.
const properties = ["a", "b", "c"] const years = [2015, 2016, 2017, 2018] let myArray = [ { date: 2015, prop1: "a" }, { date: 2015, prop1: "b" }, { date: 2016, prop1: "b" }, { date: 2016, prop1: "a" }, { date: 2016, prop1: "c" }, { date: 2017, prop1: "b" }, { date: 2017, prop1: "a" }, { date: 2017, prop1: "a" }, { date: 2017, prop1: "b" }, { date: 2017, prop1: "b" }, { date: 2018, prop1: "c" }, { date: 2018, prop1: "b" }, ] const ret = myArray.reduce((previousValue, currentValue) => { if(!previousValue[currentValue.date]) { previousValue[currentValue.date] = {} } if(!previousValue[currentValue.date][currentValue.prop1]) { previousValue[currentValue.date][currentValue.prop1] = 1 } else { previousValue[currentValue.date][currentValue.prop1]++; } return previousValue; }, {}) console.log(ret)