我有一个项目的主列表,该列表是对象的嵌套数组,我也有一个选定的列表。.
let masterList = [{
category_id: 1,
meta_list: [{
name: "Cuisine",
id: "QWEQWEQWE",
is_multiselect: false,
item_list: ["Arabian", "Indian"]
}, {
name: "Cost for Two",
id: "SFDFSDASDASDASD",
is_multiselect: true,
item_list: [
"AED 0 - 100",
"AED 100 - 200",
"Greater Than AED 200"
]
}]
}, {
category_id: 2,
meta_list: [{
name: "Cat 2",
id: "cat2",
is_multiselect: false,
item_list: ["cat 2 1", "cat 2 2"]
}, {
name: "cuisine 2",
id: "cui2",
is_multiselect: true,
item_list: ["cu1", "cu2"]
}]
}];
let selectedList = [{
category_id: 1,
meta_list: [{
name: "Cuisine",
id: "QWEQWEQWE",
is_multiselect: false,
item_list: ["Arabian"]
}, {
name: "Cost for Two",
id: "SFDFSDASDASDASD",
is_multiselect: true,
item_list: [
"AED 100 - 200",
"Greater Than AED 200"
]
}]
}, {
category_id: 2,
meta_list: [{
name: "cuisine 2",
id: "cui2",
is_multiselect: true,
item_list: ["cu1"]
}]
}];
使用masterList和选择的列表,我希望有一个namedList 必须看起来像这样
[{
category_id: 1,
meta_list: [{
name: "Cuisine",
id: "QWEQWEQWE",
is_multiselect: false,
item_list: ["Arabian", "Indian"],
sel_list: ["Arabian"]
}, {
name: "Cost for Two",
id: "SFDFSDASDASDASD",
is_multiselect: true,
item_list: [
"AED 0 - 100",
"AED 100 - 200",
"Greater Than AED 200"
],
sel_list: [
"AED 100 - 200",
"Greater Than AED 200"
]
}]
}, {
category_id: 2,
meta_list: [{
name: "Cat 2",
id: "cat2",
is_multiselect: false,
item_list: ["cat 2 1", "cat 2 2"],
sel_list: ["cat 2 2"]
}, {
name: "cuisine 2",
id: "cui2",
is_multiselect: true,
item_list: ["cu1", "cu2"],
sel_list: ["cu1"]
}]
}];
我希望具有与masterList相同的项目和结构的期望列表,除了它具有另一个属性sel_list
之外,该属性的值将是{{1 }}数组。
item_list
和selected_list
的区别在于masterList
中的selectedList
属性是item_list
中selectedList
的子集
如您在示例中所见,item_list
也可以有一个附加项目
masterList
masterList
不在{
name: "Cat 2",
id: "cat2",
is_multiselect: false,
item_list: ["cat 2 1", "cat 2 2"],
}
中。
我该如何实现?
编辑:我目前正在这样做
[{
category_id: 1,
meta_list: [{
name: "Cuisine",
id: "QWEQWEQWE",
is_multiselect: false,
item_list: ["Arabian", "Indian"],
sel_list: ["Arabian"]
}, {
name: "Cost for Two",
id: "SFDFSDASDASDASD",
is_multiselect: true,
item_list: [
"AED 0 - 100",
"AED 100 - 200",
"Greater Than AED 200"
],
sel_list: [
"AED 100 - 200",
"Greater Than AED 200"
]
}]
}, {
category_id: 2,
meta_list: [{
name: "Cat 2",
id: "cat2",
is_multiselect: false,
item_list: ["cat 2 1", "cat 2 2"],
sel_list: ["cat 2 2"]
}, {
name: "cuisine 2",
id: "cui2",
is_multiselect: true,
item_list: ["cu1", "cu2"],
sel_list: ["cu1"]
}]
}]
使用4个forEach循环。我发现我的方法效率不高而且非常凌乱,所以有更好的方法吗?
答案 0 :(得分:4)
使用json过滤方法:
let masterList = [
{
category_id: 1,
meta_list: [
{
name: "Cuisine",
id: "QWEQWEQWE",
is_multiselect: false,
item_list: ["Arabian", "Indian"]
},
{
name: "Cost for Two",
id: "SFDFSDASDASDASD",
is_multiselect: true,
item_list: [
"AED 0 - 100",
"AED 100 - 200",
"Greater Than AED 200"
]
}
]
},
{
category_id: 2,
meta_list: [
{
name: "Cat 2",
id: "cat2",
is_multiselect: false,
item_list: ["cat 2 1", "cat 2 2"]
},
{
name: "cuisine 2",
id: "cui2",
is_multiselect: true,
item_list: ["cu1", "cu2"]
}
]
}
];
let selectedList = [
{
category_id: 1,
meta_list: [
{
name: "Cuisine",
id: "QWEQWEQWE",
is_multiselect: false,
item_list: ["Arabian"]
},
{
name: "Cost for Two",
id: "SFDFSDASDASDASD",
is_multiselect: true,
item_list: [
"AED 100 - 200",
"Greater Than AED 200"
]
}
]
},
{
category_id: 2,
meta_list: [
{
name: "cuisine 2",
id: "cui2",
is_multiselect: true,
item_list: ["cu1"]
}
]
}
];
masterList.forEach(cat_met_item => {
var obj = selectedList.filter(function (el) {
return cat_met_item.category_id === el.category_id;
})
cat_met_item.meta_list.forEach(met_item => {
var selObj = obj[0].meta_list.filter(function (el) {
return met_item.id === el.id;
});
if (selObj[0]) {
met_item['sel_list'] = selObj[0].item_list;
}
else {
met_item['sel_list'] = met_item.item_list[met_item.item_list.length - 1];
}
});
});
console.log(masterList);
答案 1 :(得分:2)
在这种情况下,使用Array.prototype.find()可能更好。
let masterList = [
{
category_id: 1,
meta_list: [
{
name: "Cuisine",
id: "QWEQWEQWE",
is_multiselect: false,
item_list: ["Arabian", "Indian"]
},
{
name: "Cost for Two",
id: "SFDFSDASDASDASD",
is_multiselect: true,
item_list: [
"AED 0 - 100",
"AED 100 - 200",
"Greater Than AED 200"
]
}
]
},
{
category_id: 2,
meta_list: [
{
name: "Cat 2",
id: "cat2",
is_multiselect: false,
item_list: ["cat 2 1", "cat 2 2"]
},
{
name: "cuisine 2",
id: "cui2",
is_multiselect: true,
item_list: ["cu1", "cu2"]
}
]
}
];
let selectedList = [
{
category_id: 1,
meta_list: [
{
name: "Cuisine",
id: "QWEQWEQWE",
is_multiselect: false,
item_list: ["Arabian"]
},
{
name: "Cost for Two",
id: "SFDFSDASDASDASD",
is_multiselect: true,
item_list: [
"AED 100 - 200",
"Greater Than AED 200"
]
}
]
},
{
category_id: 2,
meta_list: [
{
name: "cuisine 2",
id: "cui2",
is_multiselect: true,
item_list: ["cu1"]
}
]
}
];
masterList.forEach(master_item => {
let select_item = selectedList.find((el) => master_item.category_id === el.category_id);
master_item.meta_list.forEach(met_item => {
let select_meta = select_item.meta_list.find((el) => met_item.id === el.id);
if (select_meta) {
met_item.sel_list = select_meta.item_list;
} else {
met_item.sel_list = [met_item.item_list[met_item.item_list.length - 1]];
}
});
});
console.log(masterList)
答案 2 :(得分:2)
您可以使用reduce
进行迭代,并使用find
获得所需的物品。以下代码还处理丢失的选定/元列表项。
const exampleMasterList = [
{
category_id: 1,
meta_list: [
{
name: 'Cuisine',
id: 'QWEQWEQWE',
is_multiselect: false,
item_list: ['Arabian', 'Indian']
},
{
name: 'Cost for Two',
id: 'SFDFSDASDASDASD',
is_multiselect: true,
item_list: ['AED 0 - 100', 'AED 100 - 200', 'Greater Than AED 200']
}
]
},
{
category_id: 2,
meta_list: [
{
name: 'Cat 2',
id: 'cat2',
is_multiselect: false,
item_list: ['cat 2 1', 'cat 2 2']
},
{
name: 'cuisine 2',
id: 'cui2',
is_multiselect: true,
item_list: ['cu1', 'cu2']
}
]
}
];
const exampleSelectedList = [
{
category_id: 1,
meta_list: [
{
name: 'Cuisine',
id: 'QWEQWEQWE',
is_multiselect: false,
item_list: ['Arabian']
},
{
name: 'Cost for Two',
id: 'SFDFSDASDASDASD',
is_multiselect: true,
item_list: ['AED 100 - 200', 'Greater Than AED 200']
}
]
},
{
category_id: 2,
meta_list: [
{
name: 'cuisine 2',
id: 'cui2',
is_multiselect: true,
item_list: ['cu1']
}
]
}
];
const getDesiredList = (masterList, selectedList) =>
masterList.reduce((a, c) => {
const selectedItem = selectedList.find(ent => ent.category_id === c.category_id);
return [
...a,
{
...c,
meta_list: c.meta_list.reduce((a2, c2) => {
const meta_list_item = selectedItem && selectedItem.meta_list.find(ent => ent.id === c2.id);
return [
...a2,
{
...c2,
sel_list: meta_list_item ? meta_list_item.item_list : []
}
];
}, [])
}
];
}, []);
console.log(JSON.stringify(getDesiredList(exampleMasterList, exampleSelectedList), null, 2));
答案 3 :(得分:2)
受Mateusz Siniarski的启发,同时生成所需的输出并将reduce
替换为map
。
const derivedList = masterList.map(master => {
const selected = selectedList.find(el => el.category_id === master.category_id)
return {
...master,
meta_list: master.meta_list.map(meta => {
const { item_list } = selected.meta_list.find(el => el.id === meta.id) || {}
return {
...meta,
sel_list: item_list || [ meta.item_list[meta.item_list.length - 1] ]
}
})
}
})
变异masterList
的迭代版本:
masterList.forEach(master => {
const selected = selectedList.find(el => el.category_id === master.category_id)
master.meta_list.forEach(meta => {
const { item_list } = selected.meta_list.find(el => el.id === meta.id) || {}
meta.sel_list = item_list || [ meta.item_list[meta.item_list.length - 1] ]
})
})
答案 4 :(得分:1)
我只是使用JSON.parse(JSON.stringify(_))
深度克隆两个对象,然后将selectedList
而不是masterList
中存在的所有属性复制到masterList
对象的克隆副本中。
由于您正在处理字符串(由于JSON.stringify
,因此您可以使用item_list
将sel_list
替换为String#replace
。
现在的最后一个问题是将masterList
的数组项与selectedList
中的数组项进行匹配。一种方法是仅使用index
,但这显然不是非常安全或可靠。我建议为执行合并的方法提供一个函数,该函数将接受每个数组中的一项并确定它们是否为equal
。此功能还必须能够理解您所指的是哪个数组(即masterList
,meta_list
,item_list
...)。
这里是您问题的相当抽象的解决方案,唯一的自定义部分是最后的最后5行,它们将item_list
替换为sel_list
并管理数组匹配,其他所有内容均可重用。 (我已经将两个对象转换为字符串以节省垂直空间,您可以专注于解决方案,而无需向下滚动到它)。
let masterList = `[{"category_id":1,"meta_list":[{"name":"Cuisine","id":"QWEQWEQWE","is_multiselect":false,"item_list":["Arabian","Indian"]},{"name":"Cost for Two","id":"SFDFSDASDASDASD","is_multiselect":true,"item_list":["AED 0 - 100","AED 100 - 200","Greater Than AED 200"]}]},{"category_id":2,"meta_list":[{"name":"Cat 2","id":"cat2","is_multiselect":false,"item_list":["cat 2 1","cat 2 2"]},{"name":"cuisine 2","id":"cui2","is_multiselect":true,"item_list":["cu1","cu2"]}]}]`;
let selectedList = `[{"category_id":1,"meta_list":[{"name":"Cuisine","id":"QWEQWEQWE","is_multiselect":false,"item_list":["Arabian"]},{"name":"Cost for Two","id":"SFDFSDASDASDASD","is_multiselect":true,"item_list":["AED 100 - 200","Greater Than AED 200"]}]},{"category_id":2,"meta_list":[{"name":"cuisine 2","id":"cui2","is_multiselect":true,"item_list":["cu1"]}]}]`;
/**
* Deep merges 2 objects (if a property exists for both objects then only the original will be used)
* @param {{} | string} original Original object in object or json format
* @param {{} | string} other Other object in object or json format
* @param {(original: string | {}, other: string | {}) => boolean} manageList Function called to compare items in the arrays
* @returns {{}}
*/
function mergeJSONs(original, other, manageList) {
original = typeof original === "string" ? original : JSON.stringify(original); // Deep clone both objects
other = typeof other === "string" ? other : JSON.stringify(other);
return recursiveMerge(JSON.parse(original), JSON.parse(other), manageList);
}
/**
* Copies all the properties that exist in the `other` object to the `original` object
* @param {{}} original Object to copy the properties to
* @param {{}} other Object to copy the properties from
* @param {(original: string | {}, other: string | {}) => boolean} manageList Function called to compare items in the arrays
* @returns {{}}
*/
function recursiveMerge(original, other, manageList) {
if (original instanceof Array) {
if (!(other instanceof Array)) throw Error("Incompatible Types");
var matchedList = [];
for (var otherItem of other) {
var originalIndex = original.findIndex(function(originalItem, index) {
if (manageList.call(this, originalItem, otherItem) && !matchedList.includes(index)) return matchedList.push(index);
});
if (originalIndex === -1) original.push(otherItem);
else if (typeof otherItem === "object") recursiveMerge(original[originalIndex], otherItem, manageList);
}
} else {
if (other instanceof Array) throw Error("Incompatible Types");
for (var key in other) {
if (!(key in original)) original[key] = other[key];
else if (typeof other[key] === "object") recursiveMerge(original[key], other[key], manageList);
}
}
return original;
}
console.log(mergeJSONs(masterList, selectedList.replace(/"item_list":/g, "\"sel_list\":"), function(original, other) {
if (typeof original === "string" && typeof other === "string") return original === other;
else if (typeof original === "object" && typeof other === "object") {
if ("category_id" in original && "category_id" in other) return original.category_id === other.category_id;
if ("id" in original && "id" in other) return original.id === other.id;
}
}));