skip to Main Content

I have a json object made like this (array of object with array element)

var orders = [
  {
    "employ": {
      "id": "1",
      "name": "1_name",
    },
    "order": [
      {
        "number": "1_1",
        "desc": "1_1_desc"
      },
      {
        "number": "1_2",
        "desc": "1_2_desc"
      }      
    ]
  },
  {
    "employ": {
      "id": "2",
      "name": "2_name",
    },
    "order": [
      {
        "number": "2_1",
        "desc": "2_1_desc"
      }      
    ]
  }  
]

and I have to denormalize it to get this, a simple array of objects

[
  {
    "emp_id": "1",
    "emp_name": "1_name",
    "ord_number": "1_1",
    "ord_desc": "1_1_desc"
  },
  {
    "emp_id": "1",
    "emp_name": "1_name",
    "ord_number": "1_2",
    "ord_desc": "1_2_desc"
  },
  {
    "emp_id": "2",
    "emp_name": "2_name",
    "ord_number": "2_1",
    "ord_desc": "2_1_desc"
  }
]

I use two nested for, but I was wondering if it is possible to do it in another way, perhaps more performing.

var orders_flat = [];
for(var i = 0; i < orders.length; i++) {
  for(var a = 0; a < orders[i].order.length; a++) {
    var o = {};
    o.emp_id     = orders[i].employ.id;
    o.emp_name   = orders[i].employ.name;
    o.ord_number = orders[i].order[a].number;
    o.ord_desc   = orders[i].order[a].desc;
    orders_flat.push(o);
  }
}

TIA

2

Answers


  1. You can achieve this using the map() function along with flatMap() to flatten the array. Here’s how you can do it:

    var orders_flat = orders.flatMap(order => order.order.map(item => ({
        emp_id: order.employ.id,
        emp_name: order.employ.name,
        ord_number: item.number,
        ord_desc: item.desc
    })));
    

    This code iterates over each order object in the orders array, and for each order, it maps over its order array to create a new object with the desired structure. Finally, flatMap() is used to flatten the resulting array of arrays into a single array.

    This approach is more concise and should also perform better than using nested for loops.

    Login or Signup to reply.
  2. The double loop in itself is not really avoidable. Of course you can use map / forEach or whatever to disguise the fact that that’s what you’re doing, but in essence you’ll be doing just as many iterations, just with extra function calls and possibly useless allocations.

    Some minor changes you could do have smaller, yet faster code:

    var orders_flat = [];
    for (const { id, name, order } of orders) 
      for (let { number, desc } of order) 
        orders_flat.push({
          emp_id: id,
          emp_name: name,
          ord_number: number,
          ord_desc: desc,
        });
    

    This avoids reaching into he array multiple times per iteration (i.e. you’re doing orders[i] 4 times, which not entirely free).

    I ran a benchmark for your code, mine and the one proposed by Sunil (higher is better):

    • original: Ops/s: 3,507,858
    • for of: Ops/s: 3,740,050
    • flatMap: Ops/s: 2,062,583

    As you can see, my version is slightly faster, the flatMap version is almost twice as slow.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search