如何通过ID将对象数组组织到自身中

时间:2019-01-04 13:00:00

标签: javascript arrays

我有一个对象数组。这些对象可以是根元素或列表元素(树结构的元素)。如何遍历该数组将那些元素组织成深度为n(未知)的树(对象具有其父元素的属性-id)?

我正在尝试构建(菜单)。我已经成功地将列表元素组织到了他们的父母中。但我坚持将所有根元素放入其父母(或根)中。我遇到的问题是它没有嵌套循环(检查何时组织了一切)。

起始数据示例:https://pastebin.com/eCSZ1HgR

[
    {
     "groupId": 1,
     "parentGroupId": null
    },
    {
     "groupId": 3,
     "parentGroupId": 1
    }, ...
]

如果对象parentGroupId为null,则表示它位于树的根中。

当前,我正在使用以下代码:

for (var i = 0; i < groups.length; i++) {
  var childGroup = groups[i];

  if (childGroup.parentGroupId === null) {
    continue;
  }

  for (var j = 0; j < groups.length; j++) {
    var parentGroup = groups[j];

    if (childGroup.parentGroupId === parentGroup.groupId) {
      if (parentGroup.hasOwnProperty('children')) {
        parentGroup.children.push(childGroup);
      } else {
        parentGroup.children = [childGroup];
      }

      break;
    }
  }
}

2 个答案:

答案 0 :(得分:1)

使用Array.prototype.reduceArray.prototype.filter函数非常简单

const tree = groups.reduce((acc, group) => {
  group.children = groups.filter(g => g.parentGroupId === group.groupId);
  acc.push(group);
  return acc;
}, []).filter(g => g.parentGroupId === null);

答案 1 :(得分:0)

这是进行深度复制的一种方法:

const testInput = [
    {
     "groupId": 1,
     "parentGroupId": null
    },
    {
     "groupId": 3,
     "parentGroupId": 1
    },
    {
      "groupId": 4,
      "parentGroupId": 3
    },
    {
      "groupId": 5,
      "parentGroupId": 1
    }
];

function flatToTree(flatList, idPropName, parentPropName, childrenPropName) {

    const list = [];
    const listIndex = {};

    /* Copy the array and create an index */

    flatList.forEach(listItem => {
      const objectCopy = Object.assign({}, listItem);
      list.push(objectCopy);
      listIndex[listItem[idPropName]] = objectCopy;
    });

    /* Assign children */

    list.forEach(listItem => {
      if (listItem[parentPropName]) {
        const parent = listIndex[listItem[parentPropName]];
        if (Array.isArray(parent[childrenPropName])) {
          parent[childrenPropName].push(listItem);
        }
        else {
          parent[childrenPropName] = [listItem];
        }
      }
    });

    /* Pick the root elements */

    return list.filter(listItem => listItem[parentPropName] === null);
}

const testOutput = flatToTree(testInput, "groupId", "parentGroupId", "children");