Javascript从嵌套对象构建嵌套对象

时间:2021-05-14 13:30:43

标签: javascript

我正在尝试从现有的深层嵌套对象构建一个新对象。我似乎无法在递归模式下思考,但我遇到了一些麻烦:

oldObjArr = [{
  id:1,
  name:"Record1"
},{
  id:2,
  name:"Record2"  
},{
  id:3,
  name:"Record3",
  kids:[{
    id: 4,
    name: "Child 3-1"
  },{
    id: 5,
    name: "Child 3-2"  
  }]
}]

buildTreeNodes = (node) => {
  let data = []
  node.map(record=>{
    record["icon"] = "..."
    record["color"] = "..."
    data.push(record)
    record.kids && buildTreeNodes(record.kids)
  })
} 
let newObjArr = buildTreeNodes(oldObjArr)

这显然不起作用,但我不知道什么会起作用。生成的对象应如下所示:

[{
  id:1,
  name:"Record1",
  icon:"...",
  color: "...",
},{
  id:2,
  name:"Record2",
  icon:"...",
  color: "...",  
},{
  id:3,
  name:"Record3",
  icon:"...",
  color: "...",
  kids:[{
    id: 4,
    name: "Child 3-1",
    icon:"...",
    color: "...",
  },{
    id: 5,
    name: "Child 3-2",
    icon:"...",
    color: "...",
  }]
}]

感谢您的帮助。

4 个答案:

答案 0 :(得分:2)

罗伯特的回答是正确的。

如果碰巧你也不想改变原始对象,那么你可以这样做。

也使用 ES6 特性,为什么不使用。

const oldObjArr = [{
  id: 1,
  name: "Record1"
}, {
  id: 2,
  name: "Record2"
}, {
  id: 3,
  name: "Record3",
  kids: [{
    id: 4,
    name: "Child 3-1"
  }, {
    id: 5,
    name: "Child 3-2"
  }]
}];

function transformObject(item) {
    if (Array.isArray(item.kids))
        return { 
            ...item, icon: '...', color: '...',
            kids: item.kids.map(transformObject)
        };
    else
        return {...item, icon: '...', color: '...' };
}

const newArray = oldObjArr.map(transformObject);
console.log(newArray);

答案 1 :(得分:1)

因此,您遍历数组并获取每个对象,然后向其中添加道具。然后你检查孩子是否存在并检查是否是数组。我使用instanceof,但像@Heretic Monkey point 一样,它可以是Array.isArray。您还可以在函数前面设置类型保护,检查数组参数是否为数组,那么您不必检查 kids 是否为数组类型。

const oldObjArr = [{
  id:1,
  name:"Record1"
},{
  id:2,
  name:"Record2"  
},{
  id:3,
  name:"Record3",
  kids:[{
    id: 4,
    name: "Child 3-1"
  },{
    id: 5,
    name: "Child 3-2"  
  }]
}]

const addKeys = arr => {
  for(const obj of arr){
    obj['icon'] = "test"
    obj['color'] = "test"
    if("kids" in obj && obj.kids instanceof Array){
      addKeys(obj.kids);
    }
  }
}
  
addKeys(oldObjArr)
console.log(oldObjArr)

V2

const addKeys = arr => {
  if(!Array.isArray(arr))
    return;
  for(const obj of arr){
    if(typeof obj !== "object")
      continue;
    obj['icon'] = "test"
    obj['color'] = "test"
    if("kids" in obj){
      addKeys(obj.kids);
    }
  }
}

答案 2 :(得分:0)

好的,看看这个:

buildTreeNodes = (node) => {
  let data = node.map(record=>{
    record["icon"] = "..."
    record["color"] = "..."
    if (record.kids) record.kids = buildTreeNodes(record.kids);
    return record;
  })
  return data;
} 
let newObjArr = buildTreeNodes(oldObjArr)
console.log(newObjArr)

我认为这就是您所追求的。您必须在每次迭代 record 时返回 map,它会将其直接添加到 data 数组中。内部递归的工作原理相同。

答案 3 :(得分:0)

所有细节都在下面的演示中评论

let objArr = [{
    id: 1,
    name: "Record 1"
  }, {
    id: 2,
    name: "Record 2"
  }, {
    id: 3,
    name: "Record 3",
    kids: [{
      id: 4,
      name: "Child 3-1"
    }, {
      id: 5,
      name: "Child 3-2"
    }]
  },
  /*
  An object with a nested object not in an array
  */
  {
    id: 6,
    name: 'Record 6',
    kid: {
      id: 7,
      name: 'Child 6-1'
    }
  },
  /*
  An object that's filtered out because it doesn't have 'id' key/property
  */
  {
    no: 0,
    name: null
  },
  /*
  An object that's filtered out because it doesn't have 'id' key/property BUT has a nested object that has 'id'
  */
  {
    no: 99,
    name: 'Member 99',
    kid: {
      id: 8,
      name: 'Scion 99-1'
    }
  }
];

/*
Pass an object that has the key/value pairs that you want added to other objects
*/
const props = {
  icon: '...',
  color: '...'
};

/*
Pass...
a single object: {obj} of objArr[] 
a single key/property: 'id'
an object that contains the key/value pairs to be added to each object that has key/property of id: {props}
*/
const addProp = (obj, prop, keyVal) => {
  /* 
  Convert {props} object into a 2D array
  props = {icon: '...', color: '...'}
  ~TO~
  kvArr = [['icon', '...'], ['color', '...']]
  */
  let kvArr = Object.entries(keyVal);

  /*
  for Each key/value pair of kvArr[][]
  assign them to the (obj} if it has ['prop'] 
  as one of it's key/properties
  (in this demo it's 'id')
  */
  kvArr.forEach(([key, val]) => {
    if (obj[prop]) {
      obj[key] = val;
    }
  });

  /*
  Convert {obj} into a 2D array
  obj = {id: 3, name: "Record 3", kids: [{   id: 4, name: "Child 3-1"}, {id: 5, name: "Child 3-2"}]}
  ~TO~
  subArr = [['id', 3], ['name', "Record 3"], ['kids', [{id: 4, name: "Child 3-1"}, {id: 5, name: "Child 3-2"}]] 
*/
  let subArr = Object.entries(obj);

  /*
  for Each value of subArr[][] (ie ['v'])
  if it's an [Array] call addProp and pass 
  the {obj} of subArr[][]
  */
  /* 
  if it's an {obj} do the same as above
  */
  subArr.forEach(([k, v]) => {
    if (Array.isArray(v)) {
      v.forEach(subObj => {
        addProp(subObj, prop, keyVal);
      });
    } else if (v instanceof Object) {
      addProp(v, prop, keyVal);
    }
  });
};

// Run addProp() on each {obj} of objArr[]
for (let object of objArr) {
  addProp(object, 'id', props);
}

console.log(JSON.stringify(objArr, null, 2));

相关问题