Tengo JSON: (tiene demasiadas filas, pero sería demasiado largo para pegar json completo)
"data": { "rows": [ { "row_no": "130", "sum_begin_period": "3234122.29", "sum_end_period": "3099063" }, { "row_no": "150", "sum_begin_period": "1252394", "sum_end_period": "986382" }, { "row_no": "160", "sum_begin_period": "1321400.28", "sum_end_period": "1321400" }, { "row_no": "210", "sum_begin_period": "3367691.4", "sum_end_period": "1282444" }, { "row_no": "220", "sum_begin_period": "2320199.07", "sum_end_period": "265000" }, { "row_no": "260", "sum_begin_period": "1047492.33", "sum_end_period": "1017444" }, { "row_no": "610", "sum_begin_period": "825495.3", "sum_end_period": "960385" } ] } Necesito hacer algunas operaciones matemáticas para las que necesito valores de varias filas. ¿Cómo puedo hacer eso con elegancia?
Lo que he intentado hasta ahora:
con Array.find():
let ccScore; for(const row of finance_report){ const satr_390_1 = finance_report.find((row) => row.row_no === "390"); const satr_190_1 = finance_report.find((row) => row.row_no === "190"); const satr_211_1 = finance_report.find((row) => row.row_no === "211"); const satr_600_1 = finance_report.find((row) => row.row_no === "600"); if (satr_600_1== 0) return 1; ccScore = (satr_390_1 - satr_190_1- satr_211_1) / satr_600_1; if (ccScore < 0.5) return 1; else if (ccScore >= 0.5 && ccScore < 2) return 3; else if (ccScore >= 2) return 5; } La desventaja de lo anterior es que Array.find se repite demasiadas veces.
with Array.maps(): (buscando con declaración IF dentro de una devolución de llamada de .map())
let accounting_factor; accounting_report.map((row) => { let summ = 0; if (row.row_no === "480") summ += parseInt(row.sum_end_period); if (row.row_no === "490") summ += parseInt(row.sum_end_period); if (row.row_no === "130") { accounting_factor = parseInt(row.sum_end_period) > parseInt(summ) ? false : true; } }); La desventaja de lo anterior es SI se repite.
¿Existe un enfoque más elegante que no me obligue a repetir mi código y me permita extraer objetos (de la matriz de "filas") con ciertas filas. fila_no y luego realizar la operación?
PD: si Array.reduce() puede resolver el problema, agradecería un ejemplo.
¿ Array.filter haría el trabajo?
const rowNrsINeed = [220, 130, 800]; const filtered = retrieveData().data.rows.filter(row => rowNrsINeed.find(no => no === +row.row_no)); filtered.forEach( r => console.log(`row: ${r.row_no}; sum_begin_period: ${r.sum_end_period}`) ) for (let row of filtered) { // ... do stuff with each found row } function retrieveData() { return { "data": { "rows": [{ "row_no": "130", "sum_begin_period": "3234122.29", "sum_end_period": "3099063" }, { "row_no": "150", "sum_begin_period": "1252394", "sum_end_period": "986382" }, { "row_no": "160", "sum_begin_period": "1321400.28", "sum_end_period": "1321400" }, { "row_no": "210", "sum_begin_period": "3367691.4", "sum_end_period": "1282444" }, { "row_no": "220", "sum_begin_period": "2320199.07", "sum_end_period": "265000" }, { "row_no": "260", "sum_begin_period": "1047492.33", "sum_end_period": "1017444" }, { "row_no": "610", "sum_begin_period": "825495.3", "sum_end_period": "960385" } ] } }; }Reestructurar los datos de la siguiente manera
let rows = {} original.data.rows.forEach(row => rows[row.row_no] = row) // USAGE rows[ROW_NUM].sum_end_periodPuede probar esto, creo que será más rápido porque una tupla de valor clave es un objeto indexado y el programa no tendrá que iterar sobre cada elemento de la matriz.
Asigne sus datos a filas usando una función de reducción.
const mapped = data.rows.reduce((a,v)=>{a[v.row_no]=v;return a},{})Ahora sus filas están indexadas por row_no
mapped['100']También puede usar la desestructuración en su reducción. (gracias jsNOOb)
const mapped = data.rows.reduce((a,v)=>({...a, [v.row_no]: v}),{}) const wantedRowIds = [390,190,211,600]; const wantedRows = finance_report.filter(row => wantedRowIds.includes(+row.row_no)); const rowsById = wantedRows.reduce((acc,row) => ({...acc, [row.row_no]:row}),{}); Luego úselos como ccScore = rowsById[390] - rowsById[190] - rowsById[211] / rowsById[600];