1

hope someone can give me hints to solve my problem.

I have a given object with the following scheme:

{
 "prop1": value1,
 "prop2": value2,
 "nested1": [{A},{B}],
 "nested2": [{C},{D}],
 "nested3": [{E},{F}],
}

what I want to get from my original object is the following:

{
 items: [
 {
 "prop1": value1,
 "prop2": value2,
 "nested1": {A},
 "nested2": {C},
 "nested3": {E},
 },
 {
 "prop1": value1,
 "prop2": value2,
 "nested1": {B},
 "nested2": {D},
 "nested3": {F},
 }, 
 ]
}

the items.length is the same as the array length in original object's nested1, nested2 etc. properties (2 in this example). I cannot find a solid way to refactor the original object using javascript native functions. Any help is appreciated.

asked Aug 3, 2020 at 16:00
2
  • Do the arrays all have the same number of elements? Commented Aug 3, 2020 at 16:06
  • yes, all nested arrays in original object have the same length. Commented Aug 3, 2020 at 18:03

6 Answers 6

2

I modified your example slightly, and used strings, in order to have a valid Object. This would be one way of doing it:

const input = {
 prop1: "value1",
 prop2: "value2",
 nested1: ["A","B"],
 nested2: ["C","D"],
 nested3: ["E","F"],
};
const output = new Array(input.nested1.length).fill().map((_, i) => ({
 prop1: input.prop1,
 prop2: input.prop2,
 nested1: input.nested1[i],
 nested2: input.nested2[i],
 nested3: input.nested3[i]
}));
console.log(output);

answered Aug 3, 2020 at 16:10
Sign up to request clarification or add additional context in comments.

1 Comment

Alternative: Array.from({ length: input.nested1.length }).map((_, i) => ...)
0

Use map and destructuring

const convert = ({ nested1, nested2, nested3, ...rest }) => ({
 items: nested1.map((nested1, i) => ({
 ...rest,
 nested1,
 nested2: nested2[i],
 nested3: nested3[i],
 }))
});
const obj = {
 prop1: 'value1',
 prop2: 'value2',
 nested1: [{ 'A': 'a' }, { 'B': 'b' }],
 nested2: [{ 'C': 1 }, { 'D': 2 }],
 nested3: [{ 'E': 5 }, { 'F': 6 }],
};
console.log(convert(obj));

answered Aug 3, 2020 at 16:28

Comments

0

If you are a beginner then you can achieve the above task simply like this.

const input = {
 prop1: "value1",
 prop2: "value2",
 nested1: ["A","B"],
 nested2: ["C","D"],
 nested3: ["E","F"],
};
let arr1 ={
 prop1:input.prop1,
 prop2:input.prop2,
 nested1:input.nested1[0],
 nestend2:input.nested2[0],
 nested3:input.nested3[0],
}
let arr2 ={
 prop1:input.prop1,
 prop2:input.prop2,
 nested1:input.nested1[1],
 nestend2:input.nested2[1],
 nested3:input.nested3[1],
}
console.log({items:[arr1,arr2]});
answered Aug 3, 2020 at 16:28

Comments

0

A generic solution for arbitrary cases

function buildItems(obj) {
 const commonPairs = Object.entries(obj).reduce(
 (accumulate, [key, val]) =>
 Array.isArray(val) ? accumulate : { ...accumulate, [key]: val },
 {}
 )
 const arrayPairs = Object.entries(obj).reduce(
 (accumulate, [key, val]) =>
 !Array.isArray(val) ? accumulate : { ...accumulate, [key]: val },
 {}
 )
 if (Object.keys(arrayPairs).length === 0) {
 return [{ ...commonPairs }]
 }
 const res = []
 for (let i = 0; i < arrayPairs[Object.keys(arrayPairs)[0]].length; i++) {
 res.push({
 ...commonPairs,
 ...Object.keys(arrayPairs).reduce(
 (acc, key) => ({ ...acc, [key]: arrayPairs[key][i] }),
 {}
 ),
 })
 }
 return res
}
console.log(
 "1)",
 buildItems({
 prop1: "value1",
 prop2: "value2",
 nested1: [{ A: 1 }, { B: 1 }, { G: 1 }],
 nested2: [{ C: 1 }, { D: 1 }, { H: 1 }],
 nested3: [{ E: 1 }, { F: 1 }, { I: 1 }],
 nested4: [{ J: 1 }, { K: 1 }, { L: 1 }],
 nested5: [{ M: 1 }, { N: 1 }, { O: 1 }],
 }),
 "\n"
)
console.log(
 "2)",
 buildItems({
 prop1: "value1",
 prop2: "value2",
 }),
 "\n"
)
console.log(
 "3)",
 buildItems({
 prop1: "value1",
 prop2: "value2",
 nested1: [{ A: 1 }, { B: 1 }, { G: 1 }],
 }),
 "\n"
)

answered Aug 3, 2020 at 16:31

Comments

0

You use Array.from with a mapping callback.

const obj = {
 "prop1": 'value1',
 "prop2": 'value2',
 "nested1": ['A','B'],
 "nested2": ['C','D'],
 "nested3": ['E','F'],
};
const res = {items: Array.from({length: obj.nested1.length}, (_,i)=>({
 prop1: obj.prop1, prop2: obj.prop2,
 nested1: obj.nested1[i],
 nested2: obj.nested2[i],
 nested3: obj.nested3[i]
}))};
console.log(res);

You could also map over any of the nested arrays.

const obj = {
 "prop1": 'value1',
 "prop2": 'value2',
 "nested1": ['A','B'],
 "nested2": ['C','D'],
 "nested3": ['E','F'],
};
const res = {
 items: obj.nested1.map((nested1,i)=>({
 prop1: obj.prop1, prop2: obj.prop2,
 nested1, nested2: obj.nested2[i], nested3: obj.nested3[i]
 }))
}
console.log(res);

answered Aug 3, 2020 at 16:32

Comments

0

Here's a fully generic solution, you don't need to know the names of the properties, not even any name of the property containing the array. This works for any amount of properties, as long as the structure is similar to the example in the question.

const source = {
 "prop1": 'value1',
 "prop2": 'value2',
 "nested1": [{A: 1}, {B: 2}],
 "nested2": [{C: 2}, {D: 4}],
 "nested3": [{E: 5}, {F: 6}]
 },
 items = [];
let len = 0;
// Get the length of the nested arrays
for (const [key, value] of Object.entries(source)) {
 if (Array.isArray(value)) {
 len = value.length;
 break;
 }
}
// Create item array objects
for (let n = 0; n < len; n++) {
 items.push({});
 for (const [key, value] of Object.entries(source)) {
 items[n][key] = (Array.isArray(value)) ? value[n] : value;
 }
}
console.log(items);

At first the code simply searches for the first array, and then stores the length of the found array. After found the length, the new objects and their properties are pushed to items array. Whether the value is directly the property value, or taken from the array, is determined by the type of the property.

answered Aug 3, 2020 at 16:38

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.