I want to convert an group of nested arrays into an array of objects with the collected information from the nested arrays:
BEFORE:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
AFTER:
[
{firstName: 'Bob', lastName: 'Lob', age: 22, role: 'salesperson'},
{firstName: 'Mary', lastName: 'Joe', age: 32, role: 'director'}
]
Here is the function I wrote to solve this but I can't quite see where the loop is going wrong:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
for (var y = 0; y < employeeData[i][y].length; y++) {
newObject[employeeData[i][y][0]] = employeeData[i][y][1];
}
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
I want to convert an group of nested arrays into an array of objects with the collected information from the nested arrays:
BEFORE:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
AFTER:
[
{firstName: 'Bob', lastName: 'Lob', age: 22, role: 'salesperson'},
{firstName: 'Mary', lastName: 'Joe', age: 32, role: 'director'}
]
Here is the function I wrote to solve this but I can't quite see where the loop is going wrong:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
for (var y = 0; y < employeeData[i][y].length; y++) {
newObject[employeeData[i][y][0]] = employeeData[i][y][1];
}
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
Thanks in advance.
Share Improve this question edited Dec 6, 2017 at 19:27 Scott Marcus 65.8k6 gold badges53 silver badges80 bronze badges asked Dec 6, 2017 at 19:24 knox-flaneurknox-flaneur 1491 gold badge2 silver badges15 bronze badges 3- "I can't quite see where the loop is going wrong" I cannot either because I do not know what your code is producing. Can you give an example of what your output looks like now? – takendarkk Commented Dec 6, 2017 at 19:25
- I notice that you never use the variable x – TallChuck Commented Dec 6, 2017 at 19:28
- As you can see after editing the question to include a code snippet, the code does work, you are simply only working with the first two array elements and need to expand it to include all the data. – Scott Marcus Commented Dec 6, 2017 at 19:28
8 Answers
Reset to default 10What's wrong with your code:
The third level for
loop is messed up. It should be removed:
for (var y = 0; y < employeeData[i][x].length; y++) {
// ^ by the way this should be x not y (not fixing the problem though)
because the third level arrays contain 2 elements that you need to use at the same time (as key-value), the for
loop for them should be removed.
Fix:
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
Fixed code example:
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
Alternative solution:
You can map
employeeData
array into a new array, reduce
ing every sub-array into an object like this:
var result = employeeData.map(function(sub) {
return sub.reduce(function(obj, pair) {
obj[ pair[0] ] = pair[1];
return obj;
}, {});
});
Which can be shortened using ES6's arrow functions to:
let result = employeeData.map(sub => sub.reduce((obj, pair) => (obj[pair[0]] = pair[1], obj), {}));
Example:
let employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
];
let result = employeeData.map(sub => sub.reduce((obj, pair) => (obj[pair[0]] = pair[1], obj), {}));
console.log(result);
How to fix your code
You only need 2 for loops: 1. iterate the array 2. iterate the sub arrays and construct the object
var employeeData = [[["firstName","Bob"],["lastName","Lob"],["age",22],["role","salesperson"]],[["firstName","Mary"],["lastName","Joe"],["age",32],["role","director"]]]
function transformData(employeeData) {
let newObject;
const newArr = [];
for (var i = 0; i < employeeData.length; i++) {
newObject = {}; // init new object
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1]; // iterate inner arrays and assign properties to object
}
newArr.push(newObject);
}
return newArr;
}
console.log(transformData(employeeData));
Another option is to use a combination of Array#map to iterate the outer array and Array#reduce to construct an object from the inner arrays:
const employeeData = [[["firstName","Bob"],["lastName","Lob"],["age",22],["role","salesperson"]],[["firstName","Mary"],["lastName","Joe"],["age",32],["role","director"]]]
const result = employeeData.map((arr) =>
arr.reduce((o, [key, value]) => (o[key] = value, o), {})
);
console.log(result);
The issue is your use of the variables x and y
For one thing, there's the line
for (var y = 0; y < employeeData[i][y].length; y++)
Perhaps you meant instead to use employeeData[i][x].length
, because as you have it here, it is going to behave very strangely.
However, you can entirely eliminate the variable y
if you replace it with x
(which, in your implementation is never even used)
Here's my suggested edits to your function:
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
Running your example with these changes I got correct output:
[
{
firstName: 'Bob',
lastName: 'Lob',
age: 22,
role: 'salesperson'
},
{
firstName: 'Mary',
lastName: 'Joe',
age: 32,
role: 'director'
}
]
The problmem you face can be solved using for loops, as you were trying, if you use your indexes correctly. If you format your data as I did, you will see that there is three levels for your indexes your [i,x,y];
for example for employeeData[0] you should get:
[
['firstName', 'Bob'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
]
then for employeeData[0][0] you should get:
['firstName', 'Bob']
and for employeeData[0][0][0] you should get: 'firstName'
To access 'Bob' you would need to employeeData[0][0][1] and since you know that there is only two elements in this inner array you don´t need to loop though it. as @TallChuck suggested great part of your problem stems from forgetting to use your x index.
var employeeData = [
[
['firstName', 'Bob'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
newObject[employeeData[i][x][0]] = employeeData[i][x][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
EDIT
You could also make some more complex solutions if you pay attention to your indexes. Say you have the following data:
var employeeData = [
[
['firstName', 'Bob', 'weight', '80kg'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary', 'eye color', 'green'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
Then the solution I gave before wouldn´t work directly. But if you look closely you will see that in some of the arrays your field names are located in the positions 0, 2 of the Y index. Which means that your field names are in a pair positions and the filed values in the odd positions. So you can actually make a loop through y and just check if the Y index is divisible by 2.
if(y % 2 == 0 ..){}
And do this only if there is an accompanying odd value thus
if(y % 2 == 0 && employeeData[i][x][y+1]){..}
The full code is below.
var employeeData = [
[
['firstName', 'Bob', 'weight', '80kg'],
['lastName', 'Lob'],
['age', 22],
['role', 'salesperson']
],
[
['firstName', 'Mary', 'eye color', 'green'],
['lastName', 'Joe'],
['age', 32],
['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var x = 0; x < employeeData[i].length; x++) {
for (var y = 0; y < employeeData[i][x].length; y++) {
if(y % 2 == 0 && employeeData[i][x][y+1]){
newObject[employeeData[i][x][y]] = employeeData[i][x][y+1];
}
}
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));
This is quite easy to do in a single line. Javascript has a function just for this.
const employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
const res = employeeData.map(data => Object.fromEntries(data))
console.log(res)
Cheers
You may just want to use a Map
instead of an Object
for each set of values in the outer array.
Then it's a very simple conversion of new Map(data);
. Maps were added to the spec for these kinds of datasets.
var employeeData = [
[['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']],
[['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']]
];
const res = employeeData.map(a => new Map(a));
for (const m of res) {
console.log(m.get("firstName"));
}
But if you do ultimately want Object
types in the array, then you can convert the each Map()
.
var employeeData = [
[['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']],
[['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']]
];
const res = employeeData.map(a => new Map(a));
for (const m of res) {
console.log(m.get("firstName"));
}
const oRes = res.map(m => Object.assign({}, ...Array.from(m.entries()).map(([k,v]) => ({[k]:v}))));
console.log(oRes);
This is a lot easier to accomplish with map and reduce
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
var d = employeeData.map(
x=>x.reduce((a,b)=>{a[b[0]]=b[1];return a;},{})
)
console.log(d)
Others have pointed out how the use of the map
array function can simplify your task and those are good solutions (much better than counting loops), but they don't address the question you actually asked.
Your code actually works just fine, you just didn't extract all the data that was available to you. You only got the first and last name. By adding two more lines you can get the rest of the data. Also, and the second loop isn't even necessary (it's not hurting you, but it doesn't actually help because you never use the x
counter anywhere).
var employeeData = [
[
['firstName', 'Bob'], ['lastName', 'Lob'], ['age', 22], ['role', 'salesperson']
],
[
['firstName', 'Mary'], ['lastName', 'Joe'], ['age', 32], ['role', 'director']
]
]
function transformData(employeeData) {
let newObject = {};
let newArr = [];
for (var i = 0; i < employeeData.length; i++) {
for (var y = 0; y < employeeData[i][y].length; y++) {
newObject[employeeData[i][y][0]] = employeeData[i][y][1];
// Now you have to get the next two array elements as well:
newObject[employeeData[i][y+1][0]] = employeeData[i][y+1][1];
newObject[employeeData[i][y+2][0]] = employeeData[i][y+2][1];
}
newArr.push(newObject);
newObject = {};
}
return newArr;
}
console.log(transformData(employeeData));