4

I've got some headers and peopleData:

const headers = ["name", "age", "nationality"]

const peopleData = [
  ["John", 31, "Spanish"],
  ["Jane", 41, "Italian"],
  ["Johnson", 11, "Thai"],
  ["Rob", 13, "Japanese"],
]

I want to combine both and return an array of objects looking like:

[{
  name: "John",
  age: 31,
  nationality: "Spanish"
}, {
  name: "Jane",
  age: 41,
  nationality: "Italian"
}, {
  name: "Johnson",
  age: 11,
  nationalityL: "Thai"
}, {
  name: "Rob",
  age: 13,
  nationality: "Japanese"
}]

So far I came up to this:

const people = peopleData.map((person, i) => {
  return headers.map((header, index) => {
    return {
      [header]: person[index]
    }
  })
})

This solution does not work since it creates nested objects:

[[{
  name: "John"
}, {
  age: 31
}, {
  nationality: "Spanish"
}], [{
  name: "Jane"
}, {
  age: 41
}, {
  nationality: "Italian"
}], [{
  name: "Johnson"
}, {
  age: 11
}, {
  nationality: "Thai"
}], [{
  name: "Rob"
}, {
  age: 13
}, {
  nationality: "Japanese"
}]]
SixtyEight
  • 2,220
  • 3
  • 14
  • 25
  • 1
    Any of the answers in [Creating a JavaScript Object from two arrays](https://stackoverflow.com/questions/39127989/creating-a-javascript-object-from-two-arrays) for `peopleData.length` times – Andreas Jul 16 '21 at 14:51

3 Answers3

4

Example below:

Credit to Andreas comment, better performant below

const headers = ["name", "age", "nationality"];

const peopleData = [
  ["John", 31, "Spanish"],
  ["Jane", 41, "Italian"],
  ["Johnson", 11, "Thai"],
  ["Rob", 13, "Japanese"],
];

const o = peopleData.map(a =>
  a.reduce((acc, b, i) => {
    acc[headers[i]] = b;
    return acc;
  }, {})
);

console.log(o);

In one line-er, but less performent

const headers = ["name", "age", "nationality"];

const peopleData = [
  ["John", 31, "Spanish"],
  ["Jane", 41, "Italian"],
  ["Johnson", 11, "Thai"],
  ["Rob", 13, "Japanese"],
];

const o = peopleData.map(a =>
  a.reduce((acc, b, i) => ({ ...acc, [headers[i]]: b }), {})
);

console.log(o);
ikhvjs
  • 5,316
  • 2
  • 13
  • 36
  • There's no need to constantly clone `acc` just to get that into a one-liner. Just append the new property and return `acc`. – Andreas Jul 16 '21 at 14:54
3

You can wrap your inner .map() in a call to Object.fromEntries() which will build an object for you - it takes an array of [[key, value],...] pairs, and so you can change your inner map to return a [key, value] pair array instead of objects like so:

const headers = ["name", "age", "nationality"];
const peopleData = [ ["John", 31, "Spanish"], ["Jane", 41, "Italian"], ["Johnson", 11, "Thai"], ["Rob", 13, "Japanese"], ];

const res = peopleData.map(person => Object.fromEntries(person.map(
  (val, i) => [headers[i], val]
)));

console.log(res);

Or, you can stick with your approach of returning an array of objects, but then merge the objects within the array together using Object.assign() and the spread syntax ...:

const headers = ["name", "age", "nationality"];
const peopleData = [ ["John", 31, "Spanish"], ["Jane", 41, "Italian"], ["Johnson", 11, "Thai"], ["Rob", 13, "Japanese"], ];

const res = peopleData.map(person => Object.assign(...person.map(
  (val, i) => ({[headers[i]]: val})
)));

console.log(res);
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
0

A simply solution easy to understand! Iterate all peopleData and put them in a new object using the array headers:

const headers = ["name", "age", "nationality"];
const peopleData = [["John", 31, "Spanish"],["Jane", 41, "Italian"],["Johnson", 11, "Thai"],["Rob", 13, "Japanese"]];

let result = [];

peopleData.forEach((e, i) => {   //iterate data
  result[i] = {};
  result[i][headers[0]] = e[0];
  result[i][headers[1]] = e[1];
  result[i][headers[2]] = e[2];
});

console.log(result);
AlexSp3
  • 2,201
  • 2
  • 7
  • 24