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?

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);

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"
  }
]

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);

Comments

0

You try this code :

let result = testData.flatMap(data => data.list.map(el => {
    let { list, ...rest } = data;
    return { ...rest, ...el };
}));

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);

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; 
}))

Comments

Your Answer

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.