1

I want to convert the below JSON format

let init = {
  test1: [1, 2, 3, 4, 5],
  test2: [6, 7, 8, 9, 10]
}

into this format using javascript native methods of array or object (supported in all browsers)

[{
  test1: 1,
  test2: 6
},{
  test1: 2,
  test2: 7
},{
  test1: 3,
  test2: 8
},{
  test1: 4,
  test2: 9
},{
  test1: 5,
  test2: 10
}]

I have tried with for loop and below is the code,

let keys = Object.keys(init);
let result = [];
for(let i = 0; i < keys.length; i++){
   let key = keys[i];
   for(let j = 0; j < init[key].length; j++){
      if(i === 0){
        let obj1 = {};
        obj1[key] = init[key][j];
        result.push(obj1);
    }else{
        let obj2 = result[j];
        obj2[key] = init[key][j];
    }    
  }
}
  • 2
    Can you add what you've tried so far? Thanks! – Nick Nov 14 '19 at 02:09
  • Nick, I have used simply for loop, but I want to do this with javascript native methods and couldn't think any approach on this – Narender Saharan Nov 14 '19 at 02:12
  • 1
    @ggorlen I have posted my attempt using for loop. As I am currently new on using JS native methods that's why I have used for loop. For more clarity on grouping logic, I have changed the test2 property value – Narender Saharan Nov 14 '19 at 03:29

2 Answers2

1

You could use Array.prototype.reduce() to do that.

Iterate on test1 array elements and push a new object to the array accumulator with test1 and test2 properties and their respective values.

let init = {
  test1: [1, 2, 3, 4, 5],
  test2: [6, 7, 8, 9, 10]
};

let keys = Object.keys(init);
let key1 = keys[0];
let key2 = keys[1];

let result = init[key1].reduce((acc, curr, i) => {
  acc.push({
    [key1]: curr,
    [key2]: init[key2][i]
  });

  return acc;
}, []);

console.log(result);

As of now, reduce() method is supported in most of the modern browsers. For supporting all browsers, it is better to use for loop, but instead of Object.keys() iterate on object properties or use a polyfill.

let init = {
  test1: [1, 2, 3, 4, 5],
  test2: [6, 7, 8, 9, 10]
};

let keys = [];

for (let key in init) {
  if (init.hasOwnProperty(key)) {
    keys.push(key);
  }
}

let key1 = keys[0];
let key2 = keys[1];

let result = [];

for (let i = 0; i < key1.length; i++) {
  result.push({
    [key1]: init[key1][i],
    [key2]: init[key2][i]
  });
}

console.log(result);
Nikhil
  • 6,493
  • 10
  • 31
  • 68
  • Thanks for answering. Though if I have more than two properties in init object say test1 to testn having the same length of arrays, then I think in reduce function we need to add for loop – Narender Saharan Nov 14 '19 at 06:02
  • That's right @NarenderSaharan — a `for` loop to iterate on object keys. – Nikhil Nov 14 '19 at 06:10
1

You could use a combination of for...in and Array.forEach to achieve this result in a few lines of code. If you wan't support for all browsers you can better use var instead of let though. https://caniuse.com/#search=let

var init = {
  test1: [1, 2, 3, 4, 5],
  test2: [6, 7, 8, 9, 10]
}

var result = []
for (var key in init) {
  init[key].forEach(function (item, index) {
    result[index] ? result[index][key] = item : result[index] = { [key]: item }
  })
}

console.log(result)

You could maybe simplify this a bit more by initializing your result with empty objects, that would avoid using a ternary statement. That would look like this:

Disclaimer: This won't work in IE11 because of the lack of Array.fill() support

var init = {
  test1: [1, 2, 3, 4, 5],
  test2: [6, 7, 8, 9, 10]
}

var result = new Array(Object.keys(init)[0].length).fill().map(Object);
for (var key in init) {
  init[key].forEach(function(item, index) {
    result[index][key] = item
  })
}

console.log(result)

If you do this make sure you don't create an array with Objects that are a reference to the same object in memory: Array.prototype.fill() with object passes reference and not new instance

Evertvdw
  • 827
  • 10
  • 17