0

I have an array:

let testData = [
 {
 MC: "11233",
 jobid: 113331,
 list: [
 { Q1: 1113, Q2: 333, code: "thisis1" },
 { Q1: 333, Q2: 111, code: "thisis2" },
 { Q1: 333, code: "thisis3" },
 ],
 },
 {
 MC: "332211",
 jobid: 3333,
 list: [
 { Q1: 444, Q2: 555, code: "thisis4" },
 ],
 },
];

And I want to convert it into:

[
 { MC: "11233", jobid: 113331, Q1: 1113, Q2: 333, code: "thisis1" },
 { MC: "11233", jobid: 113331, Q1: 333, Q2: 111, code: "thisis2" },
 { MC: "11233", jobid: 113331, Q1: 333, code: "thisis3" },
 { MC: "332211", jobid: 3333, Q1: 444, Q2: 555, code: "thisis4" },
]

I tried to write a recursive function like this

let newData = [];
testData.forEach((element, index) => {
 let flattedObj = {};
 deconstructeArrayObject(flattedObj, element);
});

and

const deconstructeArrayObject = (flattedObj, targetObj) => {
 let tempArr = [];
 for (let key in targetObj) {
 if (Array.isArray(targetObj[key])) {
 targetObj[key].forEach((element) => {
 tempArr.push(
 ...JSON.parse(
 JSON.stringify(
 deconstructeArrayObject(flattedObj, element, outputArray)
 )
 )
 );
 });
 } else {
 flattedObj[key] = targetObj[key];
 }
 }
 return flattedObj; // actually I want this function to return an array
};

I have no idea how should I reach my goal. Is there any hint or suggestion?

jsejcksn
34.6k5 gold badges55 silver badges79 bronze badges
asked Jul 20, 2022 at 9:23

6 Answers 6

1

Iterate the outer array, destructuring its properties, then do the same for each inner array, pushing the data you want in your result:

const input = [
 {
 MC: "11233",
 jobid: 113331,
 list: [
 { Q1: 1113, Q2: 333, code: "thisis1" },
 { Q1: 333, Q2: 111, code: "thisis2" },
 { Q1: 333, code: "thisis3" },
 ],
 },
 {
 MC: "332211",
 jobid: 3333,
 list: [
 { Q1: 444, Q2: 555, code: "thisis4" },
 ],
 },
];
const result = [];
for (const {MC, jobid, list} of input) {
 for (const {Q1, Q2, code} of list) {
 result.push(({MC, jobid, Q1, Q2, code}));
 }
}
console.log(result);

answered Jul 20, 2022 at 9:37
Sign up to request clarification or add additional context in comments.

2 Comments

But if Q1 is also an array and this cannot work... What I want is have a function to let me convert different array of object into the format I want
@CHL There is no Q1 array in your question. See creating a minimal, reproducible example.
0

How about this:

let testData = [{"MC":"11233","jobid":113331,"list":[{"Q1":1113, "test": [{ 'a' : 1}, { 'a' : 2}],"Q2":333,"code":"thisis1"},{"Q1":333,"Q2":111,"code":"thisis2"},
{"Q1":333,"code":"thisis3"}]}
,{"MC":"332211","jobid":3333,"list":[{"Q1":444,"Q2":555,"code":"thisis4"}]}]
 
const deconstructeArrayObject = (targetObj) => {
 let flattedObj = {};
 let tempArr = [];
 let arrayKeys = [];
 for (let key in targetObj) {
 // Save array keys
 if (Array.isArray(targetObj[key])) {
 arrayKeys.push(key);
 } else {
 flattedObj[key] = targetObj[key];
 }
 }
 
 // flatten array elements
 arrayKeys.forEach(key => {
 targetObj[key].forEach((element) => {
 const newEl = { ...flattedObj, ...element };
 // Recursion
 const arr = deconstructeArrayObject(newEl);
 tempArr.push(...arr);
 });
 });
 
 if(tempArr.length === 0) {
 return [flattedObj];
 }
 return tempArr;
}
let newData = [];
testData.forEach((element, index) => {
 const result = deconstructeArrayObject(element);
 newData.push(...result)
});
console.log(newData)

The result will be:

[
 {
 "MC": "11233",
 "jobid": 113331,
 "Q1": 1113,
 "Q2": 333,
 "code": "thisis1",
 "a": 1
 },
 {
 "MC": "11233",
 "jobid": 113331,
 "Q1": 1113,
 "Q2": 333,
 "code": "thisis1",
 "a": 2
 },
 {
 "MC": "11233",
 "jobid": 113331,
 "Q1": 333,
 "Q2": 111,
 "code": "thisis2"
 },
 {
 "MC": "11233",
 "jobid": 113331,
 "Q1": 333,
 "code": "thisis3"
 },
 {
 "MC": "332211",
 "jobid": 3333,
 "Q1": 444,
 "Q2": 555,
 "code": "thisis4"
 }
]
answered Jul 20, 2022 at 9:45

Comments

0

Here's a more general solution that doesn't depend on the specific key names, etc.

What you were missing was the answer to the subproblem: how do I merge multiple "deconstructed" objects in an array into my "flattedObj"?

This is done with the call to Object.assign in the function below.

function deconstructeArrayObject(obj) {
 const deconstructedObj = {};
 for (const key in obj) {
 if (Array.isArray(obj[key])) {
 Object.assign(
 deconstructedObj,
 ...obj[key].map(deconstructeArrayObject)
 );
 } else {
 deconstructedObj[key] = obj[key];
 }
 }
 return deconstructedObj;
}
// use like this
let newData = testData.map(deconstructeArrayObject);
answered Jul 20, 2022 at 9:46

Comments

0

You try this code :

let result = testData.flatMap(data => data.list.map(el => {
 let { list, ...rest } = data;
 return { ...rest, ...el };
}));
answered Jul 20, 2022 at 9:51

Comments

0

You could use Object.assing and create flattened array of new objects:

let testData = [
 {
 "MC":"11233",
 "jobid":113331,
 "list":[
 {"Q1":1113,"Q2":333,"code":"thisis1"},
 {"Q1":333,"Q2":111,"code":"thisis2"},
 {"Q1":333,"code":"thisis3"}
 ]},
 {
 "MC":"332211",
 "jobid":3333,
 "list":[
 {"Q1":444,"Q2":555,"code":"thisis4"}
 ]}
];
let result = testData.map(d1 => {
 return d1.list.map(d2 => {
 return Object.assign({ MC: d1.MC, jobid: d1.jobid }, d2)
 });
}).flat();
console.log(result);

answered Jul 20, 2022 at 9:51

Comments

0

Here is an approach using flatMap, that should return what you need.

testData.flatMap(job => job.list.map(item => {
 item.MC = job.MC; 
 item.jobid = job.jobid; 
 return item; 
}))
answered Jul 20, 2022 at 9:58

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.