简体   繁体   中英

Can I improve the efficiency of this nested for loop in JavaScript?

I use an ajax call to get data on grades based on a 12-month date range. Then I calculate the ratio of passes and fails by looping through a for loop of the dates and a nested for loop of the data. If the date and the data's date match, perform calculations for that date.

The problem is that I loop through a list of 12 with a nested for loop of up to thousands. The algorithm therefore seems to have an efficiency of x^2. How can I improve the efficiency of this algorithm? Can it be improved to 2x?

dataSet = [];

dateList = [
  01 - 2023,
  02 - 2023,
  //...
  12 - 2023,

];

$.ajax({
      url: '...',
      type: 'GET',
      global: false,
      success: function(data) {


          // Iterate through each date
          for (date of dateList) {
            var passes = 0;
            var fails = 0;
            var passFailRatio = 0;

            // Iterate through each data result
            for (result of data['results']) {
              //If data's grade date matches with date increment pass or fail
              if (result.gradeDate == date) {
                if (result.pass == true) {
                  passes++;
                } else if (result.fail == true) {
                  fails++;
                }
              }
            }

            if ((passes + fails) == 0) {
              passFailRatio = 0;
            } else {
              passFailRatio = (100 * (passes / (passes + fails))).toFixed(0);
            }

            // Push a dictionary to a list based on the date
            dataSet.push({
              'date': date,
              'passFailRatio': passFailRatio
            });
          }
    }
});

I was thinking about creating the list of dates while iterating through the data results. If the data result has a unique grade date, then add that date to the list and increment passes and fails for that date.

The algorithm as written has complexity O(n*m), with n being the length of dateList and m being the length of data[results] .

You can improve this by sorting both lists, followed by a standard merge.

The sort/merge complexity is:

  • O(n*log(n)) to sort the dates
  • O(m*log(m)) to sort the results
  • O(n+m) to merge

Merging the two sorted lists is, in pseudo-code (you'll have to convert to JavaScript):

dateIdx = 0
rsltIds = 0
passes = 0
fails = 0
while (dateIdx < length(datelist) and rsltIdx < length(results))
{
  if (results[rsltIdx].gradeDate < datelist[dateIdx])
  {
      // skip this result because there's no matching date
      ++rsltIdx;
  } else if (results[rsltIdx].gradeDate == dateList[dateIdx])
  {
    if (results[rsltIdx].pass)
      ++passes;
    else
      ++fails;
    ++rsltIdx;
  } else
  {
    // result date is greater. Compute ratio for this date.
    if (passes + fails) == 0
      passFailRatio = 0;
    else
      passFailRatio = (100 * (passes / (passes + fails))).toFixed(0);
      // Push a dictionary to a list based on the date
      dataSet.push({
        'date': datelist[dateIdx],
        'passFailRatio': passFailRatio
      });
    passes = 0;
    fails = 0;
    // and go to the next date
    ++dateIdx;
  }
}   
// Output '0' entries for any remaining dates
while (dateIdx < length(dateList))
{
  dataSet.push({
    'date': datelist[dateIdx],
    'passFailRatio': 0
  });
}
// Don't care about remaining results because there is no
// corresponding dateList entry for them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM