用 JavaScript 中的嵌套对象展平数组的第一个元素
Flattening the first element of array with nested objects in JavaScript
我把一个XML数据解析成了一个JS对象,导致所有父标签都变成了一个数组。我尝试将其展平,但我似乎无法理解递归部分。
这是嵌套对象的示例:
nestedObj: [
{
foo1:[ "A" ],
foo2: [
{
bar1: [ "B" ],
bar2: [ "C" ]
}
],
foo3: [ "D" ]
.
.
.
}
]
expectedData: {
foo1: "A" ,
foo2:
{
bar1: "B",
bar2: "C"
}
,
foo3: "D"
.
.
.
}
这是我对代码的尝试:
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];
}
它在 bar1 和 bar2 等内部数据上工作正常,但如您所见,我仍然必须 return arr[0] 才能完成我最初想要的 - 这有点矛盾到递归的努力。对此有什么想法吗?
你可以看看数组和对象。
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; }
根据示例数据,每个数组都有一个值。因此使用 [0]
。下面的代码使用递归、Object.fromEntries()
和Object.entries()
的组合来遍历对象。
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"
}
*/
我把一个XML数据解析成了一个JS对象,导致所有父标签都变成了一个数组。我尝试将其展平,但我似乎无法理解递归部分。
这是嵌套对象的示例:
nestedObj: [
{
foo1:[ "A" ],
foo2: [
{
bar1: [ "B" ],
bar2: [ "C" ]
}
],
foo3: [ "D" ]
.
.
.
}
]
expectedData: {
foo1: "A" ,
foo2:
{
bar1: "B",
bar2: "C"
}
,
foo3: "D"
.
.
.
}
这是我对代码的尝试:
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];
}
它在 bar1 和 bar2 等内部数据上工作正常,但如您所见,我仍然必须 return arr[0] 才能完成我最初想要的 - 这有点矛盾到递归的努力。对此有什么想法吗?
你可以看看数组和对象。
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; }
根据示例数据,每个数组都有一个值。因此使用 [0]
。下面的代码使用递归、Object.fromEntries()
和Object.entries()
的组合来遍历对象。
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"
}
*/