我有一个对象或对象数组,道具包含字符串,数组和其他对象。
我想将包含具有prop语言的对象的嵌套数组转换为以语言为键且对象本身为prop的对象。
让我们说我想递归地转换这个对象:
{
"WhatPage": [
{
"id": 1,
"WhatPageTranslations": [
{
"id": 1,
"title": "What",
"WhatPageId": 1,
"language": "en"
},
{
"id": 2,
"title": "Qué",
"WhatPageId": 1,
"language": "es"
},
],
"WhatPageImages": [
{
"id": 1,
"title": "image title 1",
"WhatPageId": 1,
"WhatPageImagesTranslations": [
{
"id": 1,
"title": "What",
"WhatPageImageId": 1,
"language": "en"
},
{
"id": 2,
"title": "Qué",
"WhatPageImageId": 1,
"language": "es"
},
]
},
]
}
]
}
然后我可以使用此函数检查其是否为数组或对象,然后递归转换数据:
export const transformTranslatedData = function(data) {
var clonedData = JSON.parse(JSON.stringify(data));
const transform = function(data) {
for (var prop in data) {
if (data[prop].length > 0 && data[prop] instanceof Array && data[prop][0].hasOwnProperty('language')) {
var transformedData = data[prop].reduce(function(prev, current, index) {
prev[current.language] = current;
return prev;
}, {});
data[prop] = transformedData;
} else if (data[prop] instanceof Object && !(data[prop] instanceof Array)) {
transformTranslatedData(data[prop]);
} else if (data[prop] instanceof Array) {
let array = JSON.parse(JSON.stringify(data[prop]));
array.forEach((item) => {
transformTranslatedData(item);
});
}
}
return data;
};
if (clonedData instanceof Array) {
var newData = [];
clonedData.map((item) => {
newData.push(transform(item));
});
} else if (clonedData instanceof Object && !(clonedData instanceof Array)) {
var newData = {};
newData = transform(clonedData);
}
return newData;
};
这有效,但仅适用于对象的第一级-WhatPageTranslations
-。在第二层上,当到达WhatPageImagesTranslations
时,它将转换数据,但是该数据不会附加到对象上。
如果有人知道为什么会这样,我将不胜感激!
答案 0 :(得分:1)
当您递归调用transformTranslatedData
时,它将为您传递的对象创建一个副本,并对其进行修改。因此,您要递归的对象不会被修改。
您需要将转换结果复制回原始对象。
} else if (data[prop] instanceof Object && !(data[prop] instanceof Array)) {
data[prop] = transformTranslatedData(data[prop]);
} else if (data[prop] instanceof Array) {
let array = JSON.parse(JSON.stringify(data[prop]));
data[prop] = array.map((item) => {
transformTranslatedData(item);
});
}
答案 1 :(得分:0)
我认为您可以简化您的递归函数。在您的解决方案中,您似乎正在克隆很多东西(每次递归调用时)。您可以创建一个深层副本一次,然后可以在递归函数中随意对其进行修改(如@Barmar所述)。
这极大地集中了我们的精力来检查和确定是否要转换递归中数据的“当前”部分:
const myData = {
"WhatPage": [{
"id": 1,
"WhatPageTranslations": [{
"id": 1,
"title": "What",
"WhatPageId": 1,
"language": "en"
},
{
"id": 2,
"title": "Qué",
"WhatPageId": 1,
"language": "es"
},
],
"WhatPageImages": [{
"id": 1,
"title": "image title 1",
"WhatPageId": 1,
"WhatPageImagesTranslations": [{
"id": 1,
"title": "What",
"WhatPageImageId": 1,
"language": "en"
},
{
"id": 2,
"title": "Qué",
"WhatPageImageId": 1,
"language": "es"
},
]
}, ]
}]
};
function transform(data) {
// base case
if (data instanceof Array && data.length && data[0].hasOwnProperty('language')) {
return data.reduce((acc, curr) => {
acc[curr.language] = curr;
return acc;
}, {});
}
// array but not base case
if (data instanceof Array) return data.map(transform);
// object but not base case
if (typeof data === 'object' && !(data instanceof Array)) {
for (let key in data) {
data[key] = transform(data[key]);
}
}
// primitive, so return as is
return data;
}
console.log(transform(JSON.parse(JSON.stringify(myData))));