1

I'd appreciate some help in this problem I'm trying to solve in a particular way. I'm trying to use forEach() and reduce() to transform a dataset from one format - an array of arrays - into another - an array of objects. I know that arr.forEach(i) => {...} will access each item in the array then I can use arr.reduce(acc, curr) => {...} to transform the nested arrays and its values into an object I'm having a hard time visualizing and reasoning out how to use .reduce() in the nested array to access and thus assign the key-value pairs in the object. Thanks in advance for your help and explanations.

Here's the raw data:

const theData = [
      [
          ["productName", "The Product"], 
          ["productOrigin", "Some Country"], 
          ["productNumber", 100], 
          ["comment", "Some Comment"]
      ],
      [
        ["productName", "Another Product"],
        ["productOrigin", "Some other Country"],
        ["productNumber", 45],
        ["comment", "some comment"]
      ]
    ]

The output I'm shooting for is this:

const formattedData = [
  {
    productName: "The Product", 
    productOrigin: "Some Country", 
    productNumber: 100,
    comment: "Some Comment
},
   productName: "Another Product", 
   productOrigin: "Some other Country", 
   productNumber: 45,
   comment: "Some Comment"
}

]

tedico
  • 67
  • 5

5 Answers5

4

Use Array.map, Array.reduce & Object.assign

Using Array.map, we can transform each entry in array to another value.Here in our case we will transform an array to an object.

For each array (entry in parent array), we will be using Array.reduce, where we will be reducing the array into an object. For each entry in array, we add key/value pair in object using Object.assign

const theData = [[["productName", "The Product"], ["productOrigin", "Some Country"], ["productNumber", 100], ["comment", "Some Comment"]],[["productName", "Another Product"],["productOrigin", "Some other Country"],["productNumber", 45],["comment", "some comment"]]];
    
const result = theData.map(v => v.reduce((a,[k,v]) => Object.assign(a, {[k]:v}), {}));
console.log(result);
Nikhil Aggarwal
  • 28,197
  • 4
  • 43
  • 59
2

Just use the proposed Object.fromEntries function:

const formattedData = theData.map(Object.fromEntries);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    While `Object.fromEntries` is already in stage 3, it might not be the best option due to compatibility (at least in Dec. 2018). – Angelos Chalaris Dec 03 '18 at 08:54
  • @AngelosChalaris It's trivial to polyfill, and the perfect tool for this use case. Even if you don't want to install it globally, I would recommend to reuse already written `fromEntries` code. – Bergi Dec 03 '18 at 09:23
1

You could map new objects by assinging mapped key/value pairs as objects.

const
    data = [[["productName", "The Product"], ["productOrigin", "Some Country"], ["productNumber", 100], ["comment", "Some Comment"]], [["productName", "Another Product"], ["productOrigin", "Some other Country"], ["productNumber", 45], ["comment", "some comment"]]],
    result = data.map(a => Object.assign(...a.map(([k, v]) => ({ [k]: v }))));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

Here's one option, using Array.prototype.map(), Array.prototype.reduce() and Object.assign():

const theData = [
  [
    ["productName", "The Product"],
    ["productOrigin", "Some Country"],
    ["productNumber", 100],
    ["comment", "Some Comment"]
  ],
  [
    ["productName", "Another Product"],
    ["productOrigin", "Some other Country"],
    ["productNumber", 45],
    ["comment", "some comment"]
  ]
];

const theObjects = theData.map(arr => arr.reduce((acc, val) => Object.assign(acc, {
  [val[0]]: val[1]
}), {}));

console.log(theObjects);
Angelos Chalaris
  • 6,611
  • 8
  • 49
  • 75
0

There are several ways to do that. One way is this:

const theData = [
      [
          ["productName", "The Product"], 
          ["productOrigin", "Some Country"], 
          ["productNumber", 100], 
          ["comment", "Some Comment"]
      ],
      [
        ["productName", "Another Product"],
        ["productOrigin", "Some other Country"],
        ["productNumber", 45],
        ["comment", "some comment"]
      ]
    ];
    
var formatted = [];   // start with an empty array

theData.forEach(function(arr){   // loop through the outer array level
  
  var obj = {};                  // create a blank object

  arr.forEach(function(row){   // loop through inner array rows

    obj[row[0]] = row[1];       // object's property is zero-th value, and 
                                 // its value is index 1
  });
  formatted.push(obj);           // push the object to the output array
});

console.log(formatted);
Ahmad
  • 12,336
  • 6
  • 48
  • 88