Javascript对象映射,创建父子关系形成对象
Posted
技术标签:
【中文标题】Javascript对象映射,创建父子关系形成对象【英文标题】:Javascript Object mapping, creating parent child relationship to form a object 【发布时间】:2022-01-22 17:25:36 【问题描述】:与逻辑作斗争: 尽我所能解释它。我有一个对象数组,例如:
[
categoryPath: "client/client one/client two" description: "test description",
categoryPath: "client/client one" description: "test description",
categoryPath: "research/research one" description: "test description"
]
编辑:预期的输出,我在预期的输出中做错了。 客户端一个类别应该有两个属性,如在输入对象中,我们可以看到它的第二个对象的类别路径为,客户端/客户端一个-因此对此的描述应该位于客户端一个层次结构之下。
我的需要是将它转换成如下的对象数组:
[
categoryName: 'client',
categoryId: '0',
subcategories: [
categoryId: '1',
categoryName: 'client one',
subcategories: [
categoryId: '2',
categoryName: 'client two',
attributes: [
description: 'test description '
],
],
attributes: [
description: 'test description '
,
description: 'test description '
]
,
],
attributes: []
,
categoryName: 'research',
categoryId: '0',
subcategories: [
categoryId: '1',
categoryName: 'research one',
attributes: [
description: 'test description '
],
],
,
],
attributes: []
,
我写的代码越来越复杂,不确定你是否会得到它,但是在这里:但是如果你检查我的代码,它会返回循环数组问题,并将父类别嵌套在对象中。
let baseObj =
name : '',
parentName:'',
subCat: [],
att: [],
level: 0,
let masterObj = ;
let baseId = ;
for (let i = 0; i < arr.length; i++)
//console.log(arr[i]);
let splitCat = arr[i].cat.split('/');
let addAttData = [...splitCat, att:arr[i].name];
if (!masterObj[splitCat[0]])
masterObj[splitCat[0]] = ...baseObj;
masterObj[splitCat[0]].name = splitCat[0];
getParentRec(splitCat[0], addAttData, masterObj);
console.log(JSON.stringify(masterObj,null,2));
Object.keys(masterObj).forEach((item, index) =>
//client//research level
console.log('new', item, masterObj[item]);
for(let i = masterObj[item].level ; i> 0; i--)
console.log(i, 'item', masterObj[item].level);
let obj = getObj(masterObj[item]);
console.log('obj', obj);
console.log('whole fir',masterObj[item]);
obj.forEach((objItem) =>
let prName = masterObj[item][objItem].parentName;
console.log('current', masterObj[item][objItem]);
if (prName !== item)
let newObj = ...masterObj[item][objItem];
masterObj[item][prName].subCat.push(newObj);
console.log('v',prName, masterObj[item][prName]); delete masterObj[item][objItem];
console.log('after delete', masterObj[item][objItem]);
console.log('whole',masterObj[item]);
else
console.log('masterItem', masterObj[item]);
masterObj[item].subCat.push(masterObj[item][objItem]);
console.log(item, 'final',JSON.stringify(masterObj[item], null, 2));
)
masterObj[item].level = masterObj[item].level - 1;
)
//console.log(JSON.stringify(masterObj, null, 2));
function getObj (obj)
console.log(Object.keys(obj), obj.level);
let objFound= Object.keys(obj).filter(filterItem => obj[filterItem].level === obj.level);
console.log('found', obj[objFound]);
return objFound;
function getParentRec(parentId, arrObj, masterObj)
//console.log('start', masterObj);
for (let i = 1; i< arrObj.length - 1 ;i++)
let obj = ...baseObj;
//console.log('obj', obj);
let lastObj = '';
lastObj = arrObj[i];
obj.name = lastObj;
if ( i+1 === arrObj.length - 1)
obj.att = [arrObj[arrObj.length - 1]];
obj.parentName = arrObj[i -1];
obj.level = i;
/* console.log('l', lastObj, i);
console.log('iobj', obj);
console.log('as ',masterObj[parentId][lastObj]); */
if (!masterObj[parentId][lastObj])
//console.log('wo', i);
masterObj[parentId][lastObj] = obj;
if (i >= masterObj[parentId].level)
masterObj[parentId].level = i;
//console.log('masterObj', masterObj);
return masterObj;
请帮助逻辑,它是用于创建一个像 UI 一样展开的文件夹。因此,任何具有相似父类别的东西都会出现在该层次结构中。否则它将形成一个新的层次结构,如研究。但在客户端进入父类别客户端的情况下,并创建类似兄弟级别的层次结构。
【问题讨论】:
【参考方案1】:用Array.reduce
试试这个
const data = [ categoryPath: "client/client one/client two", description: "test description", categoryPath: "client/client one", description: "test description", categoryPath: "research/research one", description: "test description"];
const transforming = data.reduce((acc, categoryPath, description) =>
const leaf = categoryPath.split('/').reduce((parent, categoryName, index) =>
acc[categoryName] = acc[categoryName] ||
categoryId: index.toString(),
categoryName: categoryName,
subcategories: [],
attributes: []
;
if (!acc[parent].subcategories.find(child => child.categoryName === categoryName))
acc[parent].subcategories.push(acc[categoryName]);
return categoryName;
, '-');
acc[leaf].attributes.push(description);
return acc;
, '-': subcategories: [] );
const result = transforming['-'].subcategories;
console.log(JSON.stringify(result));
编辑
const data = [ categoryPath: "client/client one/client two", description: "test description", categoryPath: "client/client one", description: "test description", categoryPath: "research/research one", description: "test description"];
const transforming = data.reduce((acc, categoryPath, description) =>
categoryPath.split('/').reduce((parent, categoryName, index) =>
acc[categoryName] = acc[categoryName] ||
categoryId: index.toString(),
categoryName: categoryName,
subcategories: [],
attributes: []
;
if (index > 0)
acc[categoryName].attributes.push(description)
if (!acc[parent].subcategories.find(child => child.categoryName === categoryName))
acc[parent].subcategories.push(acc[categoryName]);
return categoryName;
, '-');
return acc;
, '-': subcategories: [] );
const result = transforming['-'].subcategories;
console.log(JSON.stringify(result));
【讨论】:
谢谢@ProGu,这个reduce版本很酷,这里唯一的一点是,在“client one”级别应该有两个属性,就像我们有的Input第二个对象,categoryPath ="client/client one" 所以这意味着我们的属性将有两个对象(描述对象)。可以稍微调整一下来填满这个吗? @Nikhilattributes
部分与您在问题中的预期输出相同。 客户二、客户一和研究一有三个description
值。不确定应该是两个属性,我有什么遗漏吗?
@Nikhil 我想棘手的部分是acc
保持对每个节点的引用,当我们第二次遇到client one
时,acc['client one']
找到之前的一组,以便更新到同一个节点。
@Nikhil 在我的理解中,示例输入的根级别是client
或research
,只有description
的附加条目将无法找到任何一个节点。
检查categoryPath
是否不可用并运行acc['-'].subcategories.push(attributes: [description])
否则运行现有的categoryPath.split....
,这可能是你所期望的以上是关于Javascript对象映射,创建父子关系形成对象的主要内容,如果未能解决你的问题,请参考以下文章