Home > Enterprise >  JavaScript solution slower when dataset get larger
JavaScript solution slower when dataset get larger

Time:07-10

I have a dataset as below,

// e.g.
[{
  id: 'M1',
  description: 'Lorem description',
  fields: [{
    name: 'field_1',
    value: 'Lorem value 1'
  }]
}]

which I need to transform into,

[
  {
    id: 'M1',
    description: 'Lorem description',
    field_1: 'Lorem value 1'
  }
]

I wrote the code below to accomplish this. And it works well, but I don't think this is the best way to do it. How can I make my solution better performing? Because this is slower when the dataset gets larger.

const _sampleData = [{
    id: 'M1',
    description: 'Lorem description',
    fields: [{
      name: 'field_1',
      value: 'Lorem value 1'
    }]
  },
  {
    id: 'M2',
    description: 'Lorem description',
    fields: [{
        name: 'field_1',
        value: 'Lorem value 1'
      },
      {
        name: 'field_2',
        value: 'Lorem value 2'
      }
    ]
  }
];

function toObject(fields) {
  const out = {};
  for (const field of fields) {
    out[field.name] = field.value;
  }
  return out;
}

function getFlatSampleData() {
  const data = [];

  for (const item of _sampleData) {
    let out = {};
    for (const key in item) {
      if (Array.isArray(item[key])) {
        out = {
          ...out,
          ...toObject(item[key])
        };
      } else {
        out[key] = item[key];
      }
    }
    data.push(out);
  }

  return data;
}

console.log(getFlatSampleData());

CodePudding user response:

The part that seems to be the culprit is as follows:

        out = {
          ...out,
          ...toObject(item[key])
        };

Instead, since you want to flatten your object, you could do something like this:

let obj = [{
  id: 'M1',
  description: 'Lorem description',
  fields: [{
    name: 'field_1',
    value: 'Lorem value 1'
  }]
}];
let output = {};
let itemQueue = [obj];
let limit = 0;
while (limit < itemQueue.length) {
    for (let key in itemQueue[limit]) {
        if ((Array.isArray(itemQueue[limit][key])) || (typeof itemQueue[limit][key] === "object")) {
            if ((typeof itemQueue[limit][key].name !== "undefined") && (typeof itemQueue[limit][key].value !== "undefined")) {
                output[itemQueue[limit][key].name] = itemQueue[limit][key].value;
            } else {
                itemQueue.push(itemQueue[limit][key])
            }
        } else {
            output[key] = itemQueue[limit][key];
        }
    }
    limit  ;
}
console.log(output);

The idea is to not generate new objects always, but rather use a combination of a stack and a loop.

CodePudding user response:

The required processing time is expected to increase as data sets get larger. The code only accesses each element once and the transformation could not happen in less accesses. So from a high level computational perspective it's complexity is ok. Apart from the above code improvements I could propose the following two things.

  1. Preallocate the memory needed for the objects. Instead of calling push every time.

    function getFlatSampleData() { const data = new Array(_sampleData.length); for (const item of _sampleData) { let out = {}; for (const key in item) { if (Array.isArray(item[key])) { out = { ...out, ...toObject(item[key]) }; } else { out[key] = item[key]; } } data.push(out); } return data; }

  2. Use workers or a parallel JavaScript Framework to parallelize the process.

  • Related