根据一些键值 JavaScript 从 JSON 创建层次结构列表

Create a hierarchy list from an JSON based on some key values JavaScript

我收到了来自 BE 的 JSON:

[
  {
    "id": 51,
    "name": null,
    "parentAccountName": "test-name",
    "parentAccountId": 50
  },
  {
    "id": 87,
    "name": null,
    "parentAccountName": "nam1",
    "parentAccountId": 83
  },
  {
    "id": 86,
    "name": null,
    "parentAccountName": "nam1",
    "parentAccountId": 83
  },
  {
    "id": 85,
    "name": null,
    "parentAccountName": "Test andrei",
    "parentAccountId": 37
  },
  {
    "id": 84,
    "name": "nam1",
    "parentAccountName": "Test andrei",
    "parentAccountId": 37
  },
  {
    "id": 50,
    "name": "test-name",
    "parentAccountName": "nam1",
    "parentAccountId": 83
  },
  {
    "id": 37,
    "name": "Test andrei",
    "parentAccountName": "test-name",
    "parentAccountId": 50
  },
  {
   
    "id": 34,
    "name": null,
    "parentAccountName": "Test andrei",
    "parentAccountId": 37
  }
]

我需要根据 parentAccountId 创建帐户层次结构,规则是:检查列表中的每个条目是否有父级并分配给它,否则为创建该元素作为根元素并将其放在层次结构中的正确位置。 结果应该是:

[
  {
    parentAccountName: 'nam1',
    parentAccountId: 83,
    children: [
      {
        id: 50,
        name: 'test-name',
        parentAccountName: 'nam1',
        parentAccountId: 83,
        children: [
          {
            id: 37,
            name: 'Test andrei',
            parentAccountName: 'test-name',
            parentAccountId: 50,
            children: [
              {
                id: 85,
                name: null,
                parentAccountName: 'Test andrei',
                parentAccountId: 37,
              },
              {
                id: 84,
                name: 'nam1',
                parentAccountName: 'Test andrei',
                parentAccountId: 37,
              },
              {
                id: 34,
                name: null,
                parentAccountName: 'Test andrei',
                parentAccountId: 37,
              },
            ],
          },
          {
            id: 51,
            name: null,
            parentAccountName: 'test-name',
            parentAccountId: 50,
          },
        ],
      },
      {
        id: 87,
        name: null,
        parentAccountName: 'nam1',
        parentAccountId: 83,
      },
      {
        id: 86,
        name: null,
        parentAccountName: 'nam1',
        parentAccountId: 83,
      },
    ],
  },
];

我尝试执行递归函数并通过 parentAcountId 检查,但我做错了。此外,从 BE 获得的格式也不是很清楚。我的解决方案是:

const loadLazyData = (): void => {
    if (props.accounts) {
      setAccountsHierarchy(configureHierarchyNodes(props.accounts, 0));
    }
  };

  const configureHierarchyNodes = (hierarchy: IAccount[], parent?: number | undefined | null): TreeNode[] => {
    const result = [];
    for (const i in hierarchy) {
      if (hierarchy[i].parentAccountId == parent) {
        const children = configureHierarchyNodes(hierarchy, hierarchy[i].id);

        if (children.length) {
          hierarchy[i].children = children;
        }

        result.push({ ...hierarchy[i], key: `${i}-${hierarchy[i].id}`, label: hierarchy[i].accountDisplayName });
      }
    }
    return result;
  };

也许我遗漏了什么,但是在2天内我没有设法解决这个问题。如果有人有任何想法,我将不胜感激。提前致谢!

将数组缩减为Map,再转回数组,使用Array.filter()得到所有不带parentAccountId的节点属性。如果应该只有一个顶级父级,请改用 Array.find()

const arr = [{"id":51,"name":null,"parentAccountName":"test-name","parentAccountId":50},{"id":87,"name":null,"parentAccountName":"nam1","parentAccountId":83},{"id":86,"name":null,"parentAccountName":"nam1","parentAccountId":83},{"id":85,"name":null,"parentAccountName":"Test andrei","parentAccountId":37},{"id":84,"name":"nam1","parentAccountName":"Test andrei","parentAccountId":37},{"id":50,"name":"test-name","parentAccountName":"nam1","parentAccountId":83},{"id":37,"name":"Test andrei","parentAccountName":"test-name","parentAccountId":50},{"id":34,"name":null,"parentAccountName":"Test andrei","parentAccountId":37}]

const result = Array.from(
  arr.reduce((acc, o) => {
    const { parentAccountId: id, parentAccountName: name } = o
       
    if(!acc.has(id)) acc.set(id, { id, name }) // if the current item's parent doesn't exist, create it in the Map

    const parent = acc.get(id) // get the current parent

    parent.children ??= [] // init children if it doesn't exist
    
    if(!acc.has(o.id)) acc.set(o.id, o) // add the current item to the Map if it doesn't exist
    else Object.assign(acc.get(o.id), o) // combine it with the existing object if it does

    parent.children.push(acc.get(o.id)) // add the item to the children

    return acc
  }, new Map()).values()
).filter(o => !o.hasOwnProperty('parentAccountId'))

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

您可以采用标准算法来创建树。

结果拿走了没有自己的object的parents。

const
    getTree = (data, id, parent) => {
        const
            t = {},
            parents = new Set,
            children = new Set;

        data.forEach(o => {
            parents.add(o[parent]);
            children.add(o[id]);
            ((t[o[parent]] ??= { [id]: o[parent] }).children ??= []).push(Object.assign(t[o[id]] ??= {}, o))
        });
        
        children.forEach(Set.prototype.delete, parents);
        return [...parents].map(id => t[id]);
    },
    data = [{ id: 51, name: null, parentAccountName: "test-name", parentAccountId: 50 }, { id: 87, name: null, parentAccountName: "nam1", parentAccountId: 83 }, { id: 86, name: null, parentAccountName: "nam1", parentAccountId: 83 }, { id: 85, name: null, parentAccountName: "Test andrei", parentAccountId: 37 }, { id: 84, name: "nam1", parentAccountName: "Test andrei", parentAccountId: 37 }, { id: 50, name: "test-name", parentAccountName: "nam1", parentAccountId: 83 }, { id: 37, name: "Test andrei", parentAccountName: "test-name", parentAccountId: 50 }, { id: 34, name: null, parentAccountName: "Test andrei", parentAccountId: 37 }],
    tree = getTree(data, 'id', 'parentAccountId');

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }