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" 所以这意味着我们的属性将有两个对象(描述对象)。可以稍微调整一下来填满这个吗? @Nikhil attributes 部分与您在问题中的预期输出相同。 客户二客户一研究一有三个description值。不确定应该是两个属性,我有什么遗漏吗? @Nikhil 我想棘手的部分是acc 保持对每个节点的引用,当我们第二次遇到client one 时,acc['client one'] 找到之前的一组,以便更新到同一个节点。 @Nikhil 在我的理解中,示例输入的根级别是clientresearch,只有description 的附加条目将无法找到任何一个节点。 检查categoryPath 是否不可用并运行acc['-'].subcategories.push(attributes: [description]) 否则运行现有的categoryPath.split....,这可能是你所期望的

以上是关于Javascript对象映射,创建父子关系形成对象的主要内容,如果未能解决你的问题,请参考以下文章

Spring注解

JavaScript对象上

Spring父子容器

QT之对象父子关系

7.QT-Qt对象间的父子关系

Hibernate初探之单表映射——创建对象-关系映射文件