I parsed an XML data into a JS obj, causing all parent tags to turn into an array. I tried flattening it but I can't seem to wrap my head around the recursion part however.
Here's a sample of the nested object:
nestedObj: [
{
foo1:[ "A" ],
foo2: [
{
bar1: [ "B" ],
bar2: [ "C" ]
}
],
foo3: [ "D" ]
.
.
.
}
]
expectedData: {
foo1: "A" ,
foo2:
{
bar1: "B",
bar2: "C"
}
,
foo3: "D"
.
.
.
}
Here's my attempt at the code:
function flattenArrToObj(arr) {
for(let key in arr) {
let val = arr[key];
if(Array.isArray(val)) {
arr[key] = val[0];
} else {
flattenArrToObj(val);
}
}
return arr[0];
}
It works fine on the inner data such as bar1 and bar2 but as you can see, I still have to return arr[0] to accomplish what I wanted in the first place - which is somewhat contradicting to the effort of recursion. Any thoughts on this?
CodePudding user response:
You could have a look to array and objects.
const
getObject = object => Object.fromEntries(Object
.entries(object)
.map(([k, v]) => [k, fn(v)])
),
fn = value => {
if (Array.isArray(value)) {
return typeof value[0] === 'object'
? Object.assign({}, ...value.map(getObject))
: value.length === 1
? value[0]
: value
}
return getObject(value);
}
source = [{ foo1: ["A"], foo2: [{ bar1: ["B"], bar2: ["C"] }], foo3: ["D"] }],
result = fn(source);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Per the sample data, each array has one value. Hence the use of [0]
. The following code use a combination of recursion, Object.fromEntries()
and Object.entries()
to traverse the object.
const nestedObj = [
{
foo1:[ "A" ],
foo2: [
{
bar1: [ "B" ],
bar2: [ "C" ]
}
],
foo3: [ "D" ]
}
];
const arrToObj = val => {
let vals = Array.isArray(val) ? arrToObj(val[0]) : val;
if (typeof vals === 'object') {
return Object.fromEntries( Object.entries( vals ).map(([k, v]) => [k, arrToObj(v)]) );
} else {
return vals;
}
};
const newObj = arrToObj(nestedObj);
console.log( newObj );
/* OUTPUT
{
"foo1": "A",
"foo2": {
"bar1": "B",
"bar2": "C"
},
"foo3": "D"
}
*/
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>