以特定格式重新排列 Javascript 数组

Re-arrange a Javascript array in a specific format

请注意这不是重复的问题。

我很难找到从这个 JSON 数组开始的方法, 这是一级数组,我们可以在 "path" 属性

中获得每个对象或元素的路径
[
  {
    "name" : "a-1",
    "path" : "a-1",
    "parent": ""
  },
  {
    "name" : "a-2",
    "path" : "a-1>a-2",
    "parent": "a-1"
  },
  {
    "name" : "a-3",
    "path" : "a-1>a-2>a-3",
    "parent": "a-2"
  },
  {
    "name" : "a-4",
    "path" : "a-1>a-4",
    "parent": "a-1"
  },
  {
    "name" : "b-1",
    "path" : "b-1",
    "parent": ""
  }
]

最后的结果应该是这样的,

[
  {
    "attr": {
      "name": "a-1",
      "path": "a-1",
      "parent": ""
    },
    "children": [
      {
        "attr": {
          "name": "a-2",
          "path": "a-1>a-2",
          "parent": "a-1"
        },
        "children": [
          {
            "attr": {
              "name": "a-3",
              "path": "a-1>a-2>a-3",
              "parent": "a-2"
            }
          }
        ]
      },
      {
        "attr": {
          "name": "a-4",
          "path": "a-1>a-4",
          "parent": "a-1"
        }
      }
    ]
  },
  {
    "attr": {
      "name": "b-1",
      "path": "b-1",
      "parent": ""
    }
  }
]

我尝试将父级与过滤器和查找功能一起使用

theOneLevelArray.filter((elt, idx, arr) => {
   let parent = arr.find(e => e.componentItemNumber === elt.parentItemNumber);
   if (!parent) return true;
          (parent.children = parent.children || []).push(elt);
});

我也尝试过使用循环,然后在 'split(">")' 路径元素之后应用 reduce 函数(这种方法的代码真的很乱,这就是我没有粘贴的原因)

要使用给定路径,您可以通过检查给定 path 和临时结果来采用迭代方法。

这需要有序的数据。

var data = [{ name: "a-1", path: "a-1", parent: "" }, { name: "a-2", path: "a-1>a-2", parent: "a-1" }, { name: "a-3", path: "a-1>a-2>a-3", parent: "a-2" }, { name: "a-4", path: "a-1>a-4", parent: "a-1" }, { name: "b-1", path: "b-1", parent: "" }],
    tree = [];

data.forEach(function (object) {
    object.path.split('>').reduce(function (level, key) {
        var temp = level.find(({ attr: { name } }) => key === name);
        if (!temp) {
            temp = { attr: object, children: [] };
            level.push(temp);
        }
        return temp.children;
    }, tree);
});

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

另一种方法是使用 parent 属性 和一个临时对象作为对同名对象的引用。

这也适用于未排序的数据。

var data = [{ name: "a-1", path: "a-1", parent: "" }, { name: "a-2", path: "a-1>a-2", parent: "a-1" }, { name: "a-3", path: "a-1>a-2>a-3", parent: "a-2" }, { name: "a-4", path: "a-1>a-4", parent: "a-1" }, { name: "b-1", path: "b-1", parent: "" }],
    tree = function (data, root) {
        var r = [], o = {};
        data.forEach(function (attr) {
            var temp = { attr };
            if (o[attr.name] && o[attr.name].children) {
                temp.children = o[attr.name] && o[attr.name].children;
            }
            o[attr.name] = temp;
            if (attr.parent === root) {
                r.push(temp);
            } else {
                o[attr.parent] = o[attr.parent] || {};
                o[attr.parent].children = o[attr.parent].children || [];
                o[attr.parent].children.push(temp);
            }
        });
        return r;
    }(data, '');

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

简单的递归方法:

function getNodes(parentName) {
  const mapNode = (node) => {
    const children = getNodes(node.name);
    return children.length > 0 ?
      { attr: node, children } :
      { attr: node };
  };

  return source
     .filter(n => n.parent === parentName)
     .map(mapNode);
}

调用:getNodes('')

假定source为原数组