Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to optimize multiple Array.find()

I have JSON: (It has way too many rows, but would be too long to paste whole json)

"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"
      }
  ]
}

I need to do some math operations for which I need values from multiple rows. How can I do that elegantly?
What I have tried till now:
with 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;
  }

Disadvantage of above is Array.find is being repeated way too many times.
with Array.maps(): (searching with IF statement inside a callback of .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;
    }
  });

Disadvantage of above is IF being repeated.
Is there a more elegant approach which does not force me to repeat my code and enables me to extract objects(from "rows" array) with certain rows.row_no and then do operation?
P.S. If Array.reduce() can solve the issue, I would appreciate an example of it

like image 252
Rass_Rukh Avatar asked Feb 26 '26 19:02

Rass_Rukh


2 Answers

Restructure the data as follows

let rows = {}

original.data.rows.forEach(row => rows[row.row_no] = row)

// USAGE
rows[ROW_NUM].sum_end_period

You can try this out, I believe it'll be faster because a key value tuple is an indexed object and the program won't have to iterate over each element in the array.

like image 148
Karan Kaushik Avatar answered Feb 28 '26 07:02

Karan Kaushik


Map your data to rows using a reduction function.

const mapped = data.rows.reduce((a,v)=>{a[v.row_no]=v;return a},{})

Now your rows are indexed by row_no

mapped['100']

You can also use destructuring in your reduction. (thanks jsNOOb)

const mapped = data.rows.reduce((a,v)=>({...a, [v.row_no]: v}),{})
like image 39
Steven Spungin Avatar answered Feb 28 '26 08:02

Steven Spungin