在 javascript / node js 中找到键并用它替换值
find key and replace value with it in javascript / node js
let data = [{
system: {
id: "4gSSbjCFEorYXqrgDIP2FA",
type: "Entry",
name: "User"
},
DataDetails: {
shortOption: {
"en-us": "some value"
},
mediaFile: [{
sys: {
type: "Link",
link: "Entry",
id: "7kRzyt4PFo",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "2OspeCtNK0s",
},
},
],
mediaGalary: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
],
mediaExplore: [{
sys: {
type: "Link",
link: "Asset",
id: "euwcbds3282",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "jndsiw23912",
},
},
],
singleMediaImage: {
sys: {
type: "Link",
linkType: "Asset",
id: "7kRzyt4PFo",
},
},
},
},
{
system: {
id: "1aBOO8tu3lUsjtICuIbUM5",
type: "Entry",
name: "User"
},
DataDetails: {
short: {
"en-us": "details of shorts"
},
shortSlugOption: {
"hi-In": "options"
},
booleanField: {
kl: "true"
},
},
},
{
system: {
id: "2pOUGnI1oRD7nsrYs600HA",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: [{
sys: {
type: "Link",
link: "Entry",
id: "66rzYr2BpWL",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "1VTBHdLTdSW",
},
},
],
},
},
{
system: {
id: "66rzYr2BpWL1VTBHdLTdSW",
type: "Entry",
name: "new"
},
DataDetails: {
oneReference: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
multiReference: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
link: "Asset",
id: "h2cPiuU9jIz",
},
},
],
},
},
{
system: {
id: "cIb5mqEBRWDD6hrNmFmFE",
type: "Entry",
name: "new"
},
DataDetails: {
testingNewValue: {
"hi-IN": "jksdsdo"
}
},
},
{
system: {
id: "7kRzyt4PFrX13gHcw3Z1Ko",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: {
"en-us": "kknksdo"
}
},
},
];
let anotherObj = {
"gHcw3Z1Ko": {
status: true,
tag: [],
filename: "exute-image.jpg",
is_dir: false,
parent_uid: null,
},
"h2cPiuU9jIz": {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
"7kRzyt4PFo": {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
"euwcbds3282": {
status: true,
tag: [],
filename: "justice-league.jpg",
is_dir: false,
parent_uid: null,
},
"jndsiw23912": {
status: true,
tag: [],
filename: "batman.jpg",
is_dir: false,
parent_uid: null,
},
};
let res = data.reduce((acc, curr) => {
if (!acc[curr.system.name]) {
acc[curr.system.name] = {};
}
let detailsObj = {};
let assetArray=[];
for (let key of Object.keys(curr.DataDetails)) {
detailsObj[key] = Object.values(curr.DataDetails[key])[0];
if (typeof Object.values(curr.DataDetails[key])[0] === "object") {
Object.values(curr.DataDetails[key]).map((type) => {
if (Array.isArray(type)) {
type.map((link) => {
if (link.sys.link === "Asset") {
for (let id in anotherObj) {
if (link.sys.id === id) {
assetArray.push(anotherObj[id]);
detailsObj[key] = assetArray;
}
}
}
});
} else {
if (type.sys !== undefined) {
// for single Asset
if (type.sys.link === "Asset") {
for (let id in anotherObj) {
if (type.sys.id === id) {
detailsObj[key] = [anotherObj[id]];
}
}
}
}
}
});
}
}
acc[curr.system.name][curr.system.id] = {
title: curr.system.id,
uid: curr.system.id,
url: `/${curr.system.name}/${curr.system.id}`,
...detailsObj,
};
return acc;
}, {});
console.log(res);
我试图将两个对象数据放在一个输出中,但是通过读取 link 即资产
但在多数组列表中,输出显示为单个资产输出,因为 mediaFile
包含两个条目,但我不知道我哪里做错了,它显示给我一个值
因为我的主要目的是用 anotherObj 键数据
替换 sys:{id:erfrdvsdf}
所以它应该是这样的,例如我的输出是这样的
"User": {
"4gSSbjCFEorYXqrgDIP2FA": {
"title": "4gSSbjCFEorYXqrgDIP2FA",
"uid": "4gSSbjCFEorYXqrgDIP2FA",
"url": "/User/4gSSbjCFEorYXqrgDIP2FA",
"shortOption": "some value",
"mediaFile": {
"sys": {
"type": "Link",
"link": "Entry",
"id": "7kRzyt4PFo"
}
},
"mediaGalary": [
{
/**id:7**/
"status": true,
"tag": [],
"filename": "in-space-rk.jpg",
"is_dir": false,
"parent_uid": null
}
],
"singleMediaImage": {
"type": "Link",
"linkType": "Asset",
"id": "h2cPiuU9jIz"
}
},
},
但应该是这样的
"User": {
"4gSSbjCFEorYXqrgDIP2FA": {
"title": "4gSSbjCFEorYXqrgDIP2FA",
"uid": "4gSSbjCFEorYXqrgDIP2FA",
"url": "/User/4gSSbjCFEorYXqrgDIP2FA",
"shortOption": "some value",
"mediaFile": {
"sys": {
"type": "Link",
"link": "Entry",
"id": "7kRzyt4PFo"
}
},
"mediaGalary": [
{
"status": true,
"tag": [],
"filename": "in-space-rk.jpg",
"is_dir": false,
"parent_uid": null
},
{
"status": true,
"tag": [],
"filename": "wallpapers-6.jpg",
"is_dir": false,
"parent_uid": null
},
],
"mediaExplore": [
{
"status": true,
"tag": [],
"filename": "justice-league",
"is_dir": false,
"parent_uid": null
},
{
"status": true,
"tag": [],
"filename": "batman.jpg",
"is_dir": false,
"parent_uid": null
},
],
"singleMediaImage": [
{
"status": true,
"tag": [],
"filename": "wallpapers-6.jpg",
"is_dir": false,
"parent_uid": null
},
]
},
},
但我的预期输出正是我所期待的
由于这个原因,我在输入字段上遇到了同样的问题,因为我编写了相同的代码来获取数组中的输入字段和单个输入字段
我不知道我的代码在哪里出错
我知道这是一段很长的代码,但请帮我解决这个错误,因为我不会继续前进
您的代码中有一个错误:anotherObj
有重复的键。如果您将其注销,您会看到该对象中只有两个条目:
let anotherObj = {
gHcw3Z1Ko: {
status: true,
tag: [],
filename: "exute-image.jpg",
is_dir: false,
parent_uid: null,
},
h2cPiuU9jIz: {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
gHcw3Z1Ko: {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
};
console.log(anotherObj)
此外,mediaFile
将条目数组压缩为一个 - 您没有描述要用它做什么,所以我假设数组中的第一项就足够了。
但这可能不是您想要的(在下面的片段中,我删除了重复键的第一个条目):
let data = [{
system: {
id: "4gSSbjCFEorYXqrgDIP2FA",
type: "Entry",
name: "User"
},
DataDetails: {
shortOption: {
"en-us": "some value"
},
mediaFile: [{
sys: {
type: "Link",
link: "Entry",
id: "7kRzyt4PFo",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "2OspeCtNK0s",
},
},
],
mediaGalary: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
],
singleMediaImage: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
},
},
{
system: {
id: "1aBOO8tu3lUsjtICuIbUM5",
type: "Entry",
name: "User"
},
DataDetails: {
short: {
"en-us": "details of shorts"
},
shortSlugOption: {
"hi-In": "options"
},
booleanField: {
kl: "true"
},
},
},
{
system: {
id: "2pOUGnI1oRD7nsrYs600HA",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: [{
sys: {
type: "Link",
link: "Entry",
id: "66rzYr2BpWL",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "1VTBHdLTdSW",
},
},
],
},
},
{
system: {
id: "66rzYr2BpWL1VTBHdLTdSW",
type: "Entry",
name: "new"
},
DataDetails: {
oneReference: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
multiReference: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
link: "Asset",
id: "h2cPiuU9jIz",
},
},
],
},
},
{
system: {
id: "cIb5mqEBRWDD6hrNmFmFE",
type: "Entry",
name: "new"
},
DataDetails: {
testingNewValue: {
"hi-IN": "jksdsdo"
}
},
},
{
system: {
id: "7kRzyt4PFrX13gHcw3Z1Ko",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: {
"en-us": "kknksdo"
}
},
},
];
let anotherObj = {
h2cPiuU9jIz: {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
gHcw3Z1Ko: {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
};
// this is the function that actually merges the source
// object with anotherObj
const mergeGallery = (src, other) => {
return src.reduce((a, c) => {
if (typeof a[c.sys.id] === "undefined") a[c.sys.id] = {}
a[c.sys.id] = { ...other[c.sys.id] }
return a
}, {})
}
// just to display that the generation of conditional attributes
// can be extracted to their own functions
const getShortOption = (el) => {
const shortOption = el.system.name === "User" && el.DataDetails && el.DataDetails.shortOption ? {
shortOption: el.DataDetails.shortOption["en-us"]
} : {}
return shortOption
}
const getFormatted = (el, otherGallery) => {
return {
title: el.system.id,
uid: el.system.id,
url: `/${el.system.name}/${el.system.id}`,
...getShortOption(el),
...(el.DataDetails && el.DataDetails.mediaFile && {
mediaFile: el.DataDetails.mediaFile[0]
}),
...(el.DataDetails && el.DataDetails.mediaGalary && {
mediaGalary: mergeGallery(el.DataDetails.mediaGalary, otherGallery)
}),
...(el.DataDetails && el.DataDetails.singleMediaImage && {
singleMediaImage: el.DataDetails.singleMediaImage.sys
}),
}
}
const categorizeItems = (data) => {
return data.reduce((a, c) => {
if (typeof a[c.system.name] === "undefined") a[c.system.name] = {}
a[c.system.name][c.system.id] = getFormatted(c, anotherObj)
return a
}, {})
}
const ret = categorizeItems(data)
console.log(ret)
建议
- 条件句可以更短:
const getShortOption = (el) => {
const shortOption =
el.system.name === "User" && el.DataDetails && el.DataDetails.shortOption
? { shortOption: el.DataDetails.shortOption["en-us"], }
: {};
return shortOption;
};
// could be written as
const getShortOption = (el) => {
const shortOption = el.system.name === "User" && el.DataDetails?.shortOption?.["en-us"]
? { shortOption: el.DataDetails.shortOption["en-us"] }
: {}
return shortOption
}
如果您使用 ?.
链接,所有的条件都会更短 - 不幸的是 SO 片段不知道这种语法。
- 如果您在代码中使用英文术语,请将
Galary
的拼写更正为 Gallery
。如果您不这样做,这将是一个很好的混淆源。
您缺少一些值,因为您没有检查 linkType
。
您的循环正在检查 sys.link
但不检查 sys.linkType
.
使用:
link.sys.link === 'Asset' || link.sys.linkType === 'Asset'
和
type.sys.link === 'Asset' || type.sys.linkType === 'Asset'
此外,此行将覆盖您的数组:detailsObj[key] = [anotherObj[id]];
替换为:
assetArray.push(anotherObj[id]);
detailsObj[key] = assetArray;
需要说明的是,这段代码并不好。几点建议:
- 将您的代码拆分为更小的逻辑单元。不要嵌套 5 层循环。创建执行小操作的函数并相应地命名它们(例如,不要执行
for (let id in anotherObj) { ... }
,而是将逻辑放在名为 findAssetData
的函数中)
- 了解
Array.prototype.forEach
和Array.prototype.map
之间的区别(这段代码中的地图使用是错误的)
- 使用像 eslint 这样的代码质量工具,如果你是初学者,它会有所帮助
如果手动遍历复杂对象,事情会很快变得复杂。维护代码将是一场噩梦。有很好的开源库可用于使用简单查询遍历复杂对象。例如,JsonPath.
在下面的演示中,我使用了 JsonPath。它可以处理 Asset
和 Entry
而无需任何特殊处理。对于演示,我提供了所有 ID 的替换。
let data = getData();
let anotherObj = getAnotherObj();
let res = data.reduce((acc, curr) => {
if (!acc[curr.system.name]) {
acc[curr.system.name] = {};
}
let detailsObj = {};
Object.keys(curr.DataDetails).forEach(key => {
let values = curr.DataDetails[key];
// special handling to flatten single attribute objects
if (values.length === undefined || values.length === 0) {
let keys = Object.keys(values);
if (keys.length == 1 && typeof values[keys[0]] !== 'object') {
detailsObj[key] = values[keys[0]];
return;
}
}
// clone values to output
detailsObj[key] = !Array.isArray(values) ? Object.assign({}, values) : [...values];
// find and replace ids
let ids = jsonpath.query(detailsObj[key], '$..id');
ids.forEach((id, i) => {
if (id in anotherObj) {
if (Array.isArray(detailsObj[key]))
detailsObj[key].splice(i, 1, anotherObj[id]);
else
detailsObj[key] = anotherObj[id];
}
});
});
acc[curr.system.name][curr.system.id] = {
title: curr.system.id,
uid: curr.system.id,
url: `/${curr.system.name}/${curr.system.id}`,
...detailsObj,
};
return acc;
}, {});
document.body.insertAdjacentHTML('beforeend', `<pre>${JSON.stringify(res, undefined, 1)}</pre>`);
console.log(res);
function getData() {
return [{
system: {
id: "4gSSbjCFEorYXqrgDIP2FA",
type: "Entry",
name: "User"
},
DataDetails: {
shortOption: {
"en-us": "some value"
},
mediaFile: [{
sys: {
type: "Link",
link: "Entry",
id: "7kRzyt4PFo",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "2OspeCtNK0s",
},
},
],
mediaGalary: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
],
singleMediaImage: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
},
},
{
system: {
id: "1aBOO8tu3lUsjtICuIbUM5",
type: "Entry",
name: "User"
},
DataDetails: {
short: {
"en-us": "details of shorts"
},
shortSlugOption: {
"hi-In": "options"
},
booleanField: {
kl: "true"
},
},
},
{
system: {
id: "2pOUGnI1oRD7nsrYs600HA",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: [{
sys: {
type: "Link",
link: "Entry",
id: "66rzYr2BpWL",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "1VTBHdLTdSW",
},
},
],
},
},
{
system: {
id: "66rzYr2BpWL1VTBHdLTdSW",
type: "Entry",
name: "new"
},
DataDetails: {
oneReference: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
multiReference: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
link: "Asset",
id: "h2cPiuU9jIz",
},
},
],
},
},
{
system: {
id: "cIb5mqEBRWDD6hrNmFmFE",
type: "Entry",
name: "new"
},
DataDetails: {
testingNewValue: {
"hi-IN": "jksdsdo"
}
},
},
{
system: {
id: "7kRzyt4PFrX13gHcw3Z1Ko",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: {
"en-us": "kknksdo"
}
},
}
];
}
function getAnotherObj() {
return {
"h2cPiuU9jIz": {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
"gHcw3Z1Ko": {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
"7kRzyt4PFo": {
status: true,
tag: [],
filename: "mediaFile0.jpg",
is_dir: false,
parent_uid: null,
},
"2OspeCtNK0s": {
status: true,
tag: [],
filename: "mediaFile1.jpg",
is_dir: false,
parent_uid: null,
},
"66rzYr2BpWL": {
type: 'entry',
tag: [],
entry_details: "this is first entry ***",
is_secret: false,
},
"1VTBHdLTdSW": {
type: 'entry',
tag: [],
entry_details: "some other entry ***",
is_secret: true,
},
};
}
<script src="https://cdn.jsdelivr.net/npm/jsonpath@1.1.1/jsonpath.min.js"></script>
请注意,我还没有处理案例 "shortOption": "some value"
。无论如何,展平单值对象不是这里的重点。
或者您可以用一条语句替换原始对象中的所有资产和条目!
let data = getData();
let anotherObj = getAnotherObj();
jsonpath.apply(data, '$[*].DataDetails..[?(@.sys.id)]', e => anotherObj[e.sys.id]);
document.body.insertAdjacentHTML('beforeend', `<pre>${JSON.stringify(data, undefined, 1)}</pre>`);
console.log(data);
function getData() {
return [{
system: {
id: "4gSSbjCFEorYXqrgDIP2FA",
type: "Entry",
name: "User"
},
DataDetails: {
shortOption: {
"en-us": "some value"
},
mediaFile: [{
sys: {
type: "Link",
link: "Entry",
id: "7kRzyt4PFo",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "2OspeCtNK0s",
},
},
],
mediaGalary: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
],
singleMediaImage: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
},
},
{
system: {
id: "1aBOO8tu3lUsjtICuIbUM5",
type: "Entry",
name: "User"
},
DataDetails: {
short: {
"en-us": "details of shorts"
},
shortSlugOption: {
"hi-In": "options"
},
booleanField: {
kl: "true"
},
},
},
{
system: {
id: "2pOUGnI1oRD7nsrYs600HA",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: [{
sys: {
type: "Link",
link: "Entry",
id: "66rzYr2BpWL",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "1VTBHdLTdSW",
},
},
],
},
},
{
system: {
id: "66rzYr2BpWL1VTBHdLTdSW",
type: "Entry",
name: "new"
},
DataDetails: {
oneReference: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
multiReference: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
link: "Asset",
id: "h2cPiuU9jIz",
},
},
],
},
},
{
system: {
id: "cIb5mqEBRWDD6hrNmFmFE",
type: "Entry",
name: "new"
},
DataDetails: {
testingNewValue: {
"hi-IN": "jksdsdo"
}
},
},
{
system: {
id: "7kRzyt4PFrX13gHcw3Z1Ko",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: {
"en-us": "kknksdo"
}
},
}
];
}
function getAnotherObj() {
return {
"h2cPiuU9jIz": {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
"gHcw3Z1Ko": {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
"7kRzyt4PFo": {
status: true,
tag: [],
filename: "mediaFile0.jpg",
is_dir: false,
parent_uid: null,
},
"2OspeCtNK0s": {
status: true,
tag: [],
filename: "mediaFile1.jpg",
is_dir: false,
parent_uid: null,
},
"66rzYr2BpWL": {
type: 'entry',
tag: [],
entry_details: "this is first entry ****",
is_secret: false,
},
"1VTBHdLTdSW": {
type: 'entry',
tag: [],
entry_details: "some other entry ****",
is_secret: true,
},
};
}
<script src="https://cdn.jsdelivr.net/npm/jsonpath@1.1.1/jsonpath.min.js"></script>
let data = [{
system: {
id: "4gSSbjCFEorYXqrgDIP2FA",
type: "Entry",
name: "User"
},
DataDetails: {
shortOption: {
"en-us": "some value"
},
mediaFile: [{
sys: {
type: "Link",
link: "Entry",
id: "7kRzyt4PFo",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "2OspeCtNK0s",
},
},
],
mediaGalary: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
],
mediaExplore: [{
sys: {
type: "Link",
link: "Asset",
id: "euwcbds3282",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "jndsiw23912",
},
},
],
singleMediaImage: {
sys: {
type: "Link",
linkType: "Asset",
id: "7kRzyt4PFo",
},
},
},
},
{
system: {
id: "1aBOO8tu3lUsjtICuIbUM5",
type: "Entry",
name: "User"
},
DataDetails: {
short: {
"en-us": "details of shorts"
},
shortSlugOption: {
"hi-In": "options"
},
booleanField: {
kl: "true"
},
},
},
{
system: {
id: "2pOUGnI1oRD7nsrYs600HA",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: [{
sys: {
type: "Link",
link: "Entry",
id: "66rzYr2BpWL",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "1VTBHdLTdSW",
},
},
],
},
},
{
system: {
id: "66rzYr2BpWL1VTBHdLTdSW",
type: "Entry",
name: "new"
},
DataDetails: {
oneReference: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
multiReference: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
link: "Asset",
id: "h2cPiuU9jIz",
},
},
],
},
},
{
system: {
id: "cIb5mqEBRWDD6hrNmFmFE",
type: "Entry",
name: "new"
},
DataDetails: {
testingNewValue: {
"hi-IN": "jksdsdo"
}
},
},
{
system: {
id: "7kRzyt4PFrX13gHcw3Z1Ko",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: {
"en-us": "kknksdo"
}
},
},
];
let anotherObj = {
"gHcw3Z1Ko": {
status: true,
tag: [],
filename: "exute-image.jpg",
is_dir: false,
parent_uid: null,
},
"h2cPiuU9jIz": {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
"7kRzyt4PFo": {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
"euwcbds3282": {
status: true,
tag: [],
filename: "justice-league.jpg",
is_dir: false,
parent_uid: null,
},
"jndsiw23912": {
status: true,
tag: [],
filename: "batman.jpg",
is_dir: false,
parent_uid: null,
},
};
let res = data.reduce((acc, curr) => {
if (!acc[curr.system.name]) {
acc[curr.system.name] = {};
}
let detailsObj = {};
let assetArray=[];
for (let key of Object.keys(curr.DataDetails)) {
detailsObj[key] = Object.values(curr.DataDetails[key])[0];
if (typeof Object.values(curr.DataDetails[key])[0] === "object") {
Object.values(curr.DataDetails[key]).map((type) => {
if (Array.isArray(type)) {
type.map((link) => {
if (link.sys.link === "Asset") {
for (let id in anotherObj) {
if (link.sys.id === id) {
assetArray.push(anotherObj[id]);
detailsObj[key] = assetArray;
}
}
}
});
} else {
if (type.sys !== undefined) {
// for single Asset
if (type.sys.link === "Asset") {
for (let id in anotherObj) {
if (type.sys.id === id) {
detailsObj[key] = [anotherObj[id]];
}
}
}
}
}
});
}
}
acc[curr.system.name][curr.system.id] = {
title: curr.system.id,
uid: curr.system.id,
url: `/${curr.system.name}/${curr.system.id}`,
...detailsObj,
};
return acc;
}, {});
console.log(res);
我试图将两个对象数据放在一个输出中,但是通过读取 link 即资产
但在多数组列表中,输出显示为单个资产输出,因为 mediaFile
包含两个条目,但我不知道我哪里做错了,它显示给我一个值
因为我的主要目的是用 anotherObj 键数据
替换sys:{id:erfrdvsdf}
所以它应该是这样的,例如我的输出是这样的
"User": {
"4gSSbjCFEorYXqrgDIP2FA": {
"title": "4gSSbjCFEorYXqrgDIP2FA",
"uid": "4gSSbjCFEorYXqrgDIP2FA",
"url": "/User/4gSSbjCFEorYXqrgDIP2FA",
"shortOption": "some value",
"mediaFile": {
"sys": {
"type": "Link",
"link": "Entry",
"id": "7kRzyt4PFo"
}
},
"mediaGalary": [
{
/**id:7**/
"status": true,
"tag": [],
"filename": "in-space-rk.jpg",
"is_dir": false,
"parent_uid": null
}
],
"singleMediaImage": {
"type": "Link",
"linkType": "Asset",
"id": "h2cPiuU9jIz"
}
},
},
但应该是这样的
"User": {
"4gSSbjCFEorYXqrgDIP2FA": {
"title": "4gSSbjCFEorYXqrgDIP2FA",
"uid": "4gSSbjCFEorYXqrgDIP2FA",
"url": "/User/4gSSbjCFEorYXqrgDIP2FA",
"shortOption": "some value",
"mediaFile": {
"sys": {
"type": "Link",
"link": "Entry",
"id": "7kRzyt4PFo"
}
},
"mediaGalary": [
{
"status": true,
"tag": [],
"filename": "in-space-rk.jpg",
"is_dir": false,
"parent_uid": null
},
{
"status": true,
"tag": [],
"filename": "wallpapers-6.jpg",
"is_dir": false,
"parent_uid": null
},
],
"mediaExplore": [
{
"status": true,
"tag": [],
"filename": "justice-league",
"is_dir": false,
"parent_uid": null
},
{
"status": true,
"tag": [],
"filename": "batman.jpg",
"is_dir": false,
"parent_uid": null
},
],
"singleMediaImage": [
{
"status": true,
"tag": [],
"filename": "wallpapers-6.jpg",
"is_dir": false,
"parent_uid": null
},
]
},
},
但我的预期输出正是我所期待的
由于这个原因,我在输入字段上遇到了同样的问题,因为我编写了相同的代码来获取数组中的输入字段和单个输入字段
我不知道我的代码在哪里出错
我知道这是一段很长的代码,但请帮我解决这个错误,因为我不会继续前进
您的代码中有一个错误:anotherObj
有重复的键。如果您将其注销,您会看到该对象中只有两个条目:
let anotherObj = {
gHcw3Z1Ko: {
status: true,
tag: [],
filename: "exute-image.jpg",
is_dir: false,
parent_uid: null,
},
h2cPiuU9jIz: {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
gHcw3Z1Ko: {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
};
console.log(anotherObj)
此外,mediaFile
将条目数组压缩为一个 - 您没有描述要用它做什么,所以我假设数组中的第一项就足够了。
但这可能不是您想要的(在下面的片段中,我删除了重复键的第一个条目):
let data = [{
system: {
id: "4gSSbjCFEorYXqrgDIP2FA",
type: "Entry",
name: "User"
},
DataDetails: {
shortOption: {
"en-us": "some value"
},
mediaFile: [{
sys: {
type: "Link",
link: "Entry",
id: "7kRzyt4PFo",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "2OspeCtNK0s",
},
},
],
mediaGalary: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
],
singleMediaImage: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
},
},
{
system: {
id: "1aBOO8tu3lUsjtICuIbUM5",
type: "Entry",
name: "User"
},
DataDetails: {
short: {
"en-us": "details of shorts"
},
shortSlugOption: {
"hi-In": "options"
},
booleanField: {
kl: "true"
},
},
},
{
system: {
id: "2pOUGnI1oRD7nsrYs600HA",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: [{
sys: {
type: "Link",
link: "Entry",
id: "66rzYr2BpWL",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "1VTBHdLTdSW",
},
},
],
},
},
{
system: {
id: "66rzYr2BpWL1VTBHdLTdSW",
type: "Entry",
name: "new"
},
DataDetails: {
oneReference: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
multiReference: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
link: "Asset",
id: "h2cPiuU9jIz",
},
},
],
},
},
{
system: {
id: "cIb5mqEBRWDD6hrNmFmFE",
type: "Entry",
name: "new"
},
DataDetails: {
testingNewValue: {
"hi-IN": "jksdsdo"
}
},
},
{
system: {
id: "7kRzyt4PFrX13gHcw3Z1Ko",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: {
"en-us": "kknksdo"
}
},
},
];
let anotherObj = {
h2cPiuU9jIz: {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
gHcw3Z1Ko: {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
};
// this is the function that actually merges the source
// object with anotherObj
const mergeGallery = (src, other) => {
return src.reduce((a, c) => {
if (typeof a[c.sys.id] === "undefined") a[c.sys.id] = {}
a[c.sys.id] = { ...other[c.sys.id] }
return a
}, {})
}
// just to display that the generation of conditional attributes
// can be extracted to their own functions
const getShortOption = (el) => {
const shortOption = el.system.name === "User" && el.DataDetails && el.DataDetails.shortOption ? {
shortOption: el.DataDetails.shortOption["en-us"]
} : {}
return shortOption
}
const getFormatted = (el, otherGallery) => {
return {
title: el.system.id,
uid: el.system.id,
url: `/${el.system.name}/${el.system.id}`,
...getShortOption(el),
...(el.DataDetails && el.DataDetails.mediaFile && {
mediaFile: el.DataDetails.mediaFile[0]
}),
...(el.DataDetails && el.DataDetails.mediaGalary && {
mediaGalary: mergeGallery(el.DataDetails.mediaGalary, otherGallery)
}),
...(el.DataDetails && el.DataDetails.singleMediaImage && {
singleMediaImage: el.DataDetails.singleMediaImage.sys
}),
}
}
const categorizeItems = (data) => {
return data.reduce((a, c) => {
if (typeof a[c.system.name] === "undefined") a[c.system.name] = {}
a[c.system.name][c.system.id] = getFormatted(c, anotherObj)
return a
}, {})
}
const ret = categorizeItems(data)
console.log(ret)
建议
- 条件句可以更短:
const getShortOption = (el) => {
const shortOption =
el.system.name === "User" && el.DataDetails && el.DataDetails.shortOption
? { shortOption: el.DataDetails.shortOption["en-us"], }
: {};
return shortOption;
};
// could be written as
const getShortOption = (el) => {
const shortOption = el.system.name === "User" && el.DataDetails?.shortOption?.["en-us"]
? { shortOption: el.DataDetails.shortOption["en-us"] }
: {}
return shortOption
}
如果您使用 ?.
链接,所有的条件都会更短 - 不幸的是 SO 片段不知道这种语法。
- 如果您在代码中使用英文术语,请将
Galary
的拼写更正为Gallery
。如果您不这样做,这将是一个很好的混淆源。
您缺少一些值,因为您没有检查 linkType
。
您的循环正在检查 sys.link
但不检查 sys.linkType
.
使用:
link.sys.link === 'Asset' || link.sys.linkType === 'Asset'
和
type.sys.link === 'Asset' || type.sys.linkType === 'Asset'
此外,此行将覆盖您的数组:detailsObj[key] = [anotherObj[id]];
替换为:
assetArray.push(anotherObj[id]);
detailsObj[key] = assetArray;
需要说明的是,这段代码并不好。几点建议:
- 将您的代码拆分为更小的逻辑单元。不要嵌套 5 层循环。创建执行小操作的函数并相应地命名它们(例如,不要执行
for (let id in anotherObj) { ... }
,而是将逻辑放在名为findAssetData
的函数中) - 了解
Array.prototype.forEach
和Array.prototype.map
之间的区别(这段代码中的地图使用是错误的) - 使用像 eslint 这样的代码质量工具,如果你是初学者,它会有所帮助
如果手动遍历复杂对象,事情会很快变得复杂。维护代码将是一场噩梦。有很好的开源库可用于使用简单查询遍历复杂对象。例如,JsonPath.
在下面的演示中,我使用了 JsonPath。它可以处理 Asset
和 Entry
而无需任何特殊处理。对于演示,我提供了所有 ID 的替换。
let data = getData();
let anotherObj = getAnotherObj();
let res = data.reduce((acc, curr) => {
if (!acc[curr.system.name]) {
acc[curr.system.name] = {};
}
let detailsObj = {};
Object.keys(curr.DataDetails).forEach(key => {
let values = curr.DataDetails[key];
// special handling to flatten single attribute objects
if (values.length === undefined || values.length === 0) {
let keys = Object.keys(values);
if (keys.length == 1 && typeof values[keys[0]] !== 'object') {
detailsObj[key] = values[keys[0]];
return;
}
}
// clone values to output
detailsObj[key] = !Array.isArray(values) ? Object.assign({}, values) : [...values];
// find and replace ids
let ids = jsonpath.query(detailsObj[key], '$..id');
ids.forEach((id, i) => {
if (id in anotherObj) {
if (Array.isArray(detailsObj[key]))
detailsObj[key].splice(i, 1, anotherObj[id]);
else
detailsObj[key] = anotherObj[id];
}
});
});
acc[curr.system.name][curr.system.id] = {
title: curr.system.id,
uid: curr.system.id,
url: `/${curr.system.name}/${curr.system.id}`,
...detailsObj,
};
return acc;
}, {});
document.body.insertAdjacentHTML('beforeend', `<pre>${JSON.stringify(res, undefined, 1)}</pre>`);
console.log(res);
function getData() {
return [{
system: {
id: "4gSSbjCFEorYXqrgDIP2FA",
type: "Entry",
name: "User"
},
DataDetails: {
shortOption: {
"en-us": "some value"
},
mediaFile: [{
sys: {
type: "Link",
link: "Entry",
id: "7kRzyt4PFo",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "2OspeCtNK0s",
},
},
],
mediaGalary: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
],
singleMediaImage: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
},
},
{
system: {
id: "1aBOO8tu3lUsjtICuIbUM5",
type: "Entry",
name: "User"
},
DataDetails: {
short: {
"en-us": "details of shorts"
},
shortSlugOption: {
"hi-In": "options"
},
booleanField: {
kl: "true"
},
},
},
{
system: {
id: "2pOUGnI1oRD7nsrYs600HA",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: [{
sys: {
type: "Link",
link: "Entry",
id: "66rzYr2BpWL",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "1VTBHdLTdSW",
},
},
],
},
},
{
system: {
id: "66rzYr2BpWL1VTBHdLTdSW",
type: "Entry",
name: "new"
},
DataDetails: {
oneReference: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
multiReference: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
link: "Asset",
id: "h2cPiuU9jIz",
},
},
],
},
},
{
system: {
id: "cIb5mqEBRWDD6hrNmFmFE",
type: "Entry",
name: "new"
},
DataDetails: {
testingNewValue: {
"hi-IN": "jksdsdo"
}
},
},
{
system: {
id: "7kRzyt4PFrX13gHcw3Z1Ko",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: {
"en-us": "kknksdo"
}
},
}
];
}
function getAnotherObj() {
return {
"h2cPiuU9jIz": {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
"gHcw3Z1Ko": {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
"7kRzyt4PFo": {
status: true,
tag: [],
filename: "mediaFile0.jpg",
is_dir: false,
parent_uid: null,
},
"2OspeCtNK0s": {
status: true,
tag: [],
filename: "mediaFile1.jpg",
is_dir: false,
parent_uid: null,
},
"66rzYr2BpWL": {
type: 'entry',
tag: [],
entry_details: "this is first entry ***",
is_secret: false,
},
"1VTBHdLTdSW": {
type: 'entry',
tag: [],
entry_details: "some other entry ***",
is_secret: true,
},
};
}
<script src="https://cdn.jsdelivr.net/npm/jsonpath@1.1.1/jsonpath.min.js"></script>
请注意,我还没有处理案例 "shortOption": "some value"
。无论如何,展平单值对象不是这里的重点。
或者您可以用一条语句替换原始对象中的所有资产和条目!
let data = getData();
let anotherObj = getAnotherObj();
jsonpath.apply(data, '$[*].DataDetails..[?(@.sys.id)]', e => anotherObj[e.sys.id]);
document.body.insertAdjacentHTML('beforeend', `<pre>${JSON.stringify(data, undefined, 1)}</pre>`);
console.log(data);
function getData() {
return [{
system: {
id: "4gSSbjCFEorYXqrgDIP2FA",
type: "Entry",
name: "User"
},
DataDetails: {
shortOption: {
"en-us": "some value"
},
mediaFile: [{
sys: {
type: "Link",
link: "Entry",
id: "7kRzyt4PFo",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "2OspeCtNK0s",
},
},
],
mediaGalary: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
],
singleMediaImage: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
},
},
{
system: {
id: "1aBOO8tu3lUsjtICuIbUM5",
type: "Entry",
name: "User"
},
DataDetails: {
short: {
"en-us": "details of shorts"
},
shortSlugOption: {
"hi-In": "options"
},
booleanField: {
kl: "true"
},
},
},
{
system: {
id: "2pOUGnI1oRD7nsrYs600HA",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: [{
sys: {
type: "Link",
link: "Entry",
id: "66rzYr2BpWL",
},
},
{
sys: {
type: "Link",
link: "Entry",
id: "1VTBHdLTdSW",
},
},
],
},
},
{
system: {
id: "66rzYr2BpWL1VTBHdLTdSW",
type: "Entry",
name: "new"
},
DataDetails: {
oneReference: {
sys: {
type: "Link",
linkType: "Asset",
id: "h2cPiuU9jIz",
},
},
multiReference: [{
sys: {
type: "Link",
link: "Asset",
id: "gHcw3Z1Ko",
},
},
{
sys: {
type: "Link",
link: "Asset",
id: "h2cPiuU9jIz",
},
},
],
},
},
{
system: {
id: "cIb5mqEBRWDD6hrNmFmFE",
type: "Entry",
name: "new"
},
DataDetails: {
testingNewValue: {
"hi-IN": "jksdsdo"
}
},
},
{
system: {
id: "7kRzyt4PFrX13gHcw3Z1Ko",
type: "Entry",
name: "Dummy"
},
DataDetails: {
testingNewValue: {
"en-us": "kknksdo"
}
},
}
];
}
function getAnotherObj() {
return {
"h2cPiuU9jIz": {
status: true,
tag: [],
filename: "wallpapers-6.jpg",
is_dir: false,
parent_uid: null,
},
"gHcw3Z1Ko": {
status: true,
tag: [],
filename: "in-space-rk.jpg",
is_dir: false,
parent_uid: null,
},
"7kRzyt4PFo": {
status: true,
tag: [],
filename: "mediaFile0.jpg",
is_dir: false,
parent_uid: null,
},
"2OspeCtNK0s": {
status: true,
tag: [],
filename: "mediaFile1.jpg",
is_dir: false,
parent_uid: null,
},
"66rzYr2BpWL": {
type: 'entry',
tag: [],
entry_details: "this is first entry ****",
is_secret: false,
},
"1VTBHdLTdSW": {
type: 'entry',
tag: [],
entry_details: "some other entry ****",
is_secret: true,
},
};
}
<script src="https://cdn.jsdelivr.net/npm/jsonpath@1.1.1/jsonpath.min.js"></script>