如何将该数组映射到嵌套对象树?

时间:2018-10-22 07:57:02

标签: javascript arrays

我正在尝试在平面数组上创建树。我的输入没有任何种类的父母ID。每个元素都使用一个id,它是一种路径,格式为ancestor(n+1)-ancestor1-Grandparent-parent-id等。

例如输入为

[{"id":"1","children":[]},{"id":"1-1"}]

那么输出应该是

[{"id":"1","children":[{"id":"1-1"}]}]

并给出

[
  {
    "id": "1",
    "children": []
  },
  {
    "id": "1-1",
    "children": []
  },
  {
    "id": "1-1-1"
  },
  {
    "id": "1-2"
  },
  {
    "id": "2",
    "children": []
  },
  {
    "id": "2-1"
  }
]

然后

[{
    "id": "1",
    "children": [
      {
        "id": "1-1",
        "children": [
          {
            "id": "1-1-1"
          }
        ]
      },
      {
        "id": "1-2"
      }
    ]
  },
  {
    "id": "2",
    "children": [
      {
        "id": "2-1"
      }
    ]
  }
]

我当前的代码:

let list = [{
    "name": "Europe",
    "employeeCount": 1,
    "children": [],
    "id": "1"
  },
  {
    "name": "France",
    "employeeCount": 1,
    "children": [],
    "id": "1-1"
  },
  {
    "name": "Paris",
    "employeeCount": 1,
    "children": [],
    "id": "1-1-1"
  },
  {
    "name": "Foo Bar",
    "isInactive": false,
    "id": "1-1-1-27"
  }
]

// I try this but I am not sure how to loop...
function buildTree(list) {
  let tree = []
  for (var i = 0; i < list.length; i++) {

    if (!list[i].id.includes('-')) {
      tree.push(list[i]);
    } else {
      tree[tree.length - 1].children.push(list[i]);
    }
  }
  return tree;
}


let tree = buildTree(list)

console.log(tree[0].children[0].children[0] === "Paris")

与:How to efficiently build a tree from a flat structure?

1 个答案:

答案 0 :(得分:0)

由于数组已排序,因此可以使用递归函数来实现:

const delimiter = '-';
const delimiterCount = x => x.id.split('').reduce((acc, c) => acc + (c === delimiter), 0);


function descend(tree, node, count) {
	if (count == 0) {
		tree.push(node);
		return;
	}

	return descend(tree[tree.length - 1].children, node, count - 1);
}

function buildTree(list){
	let tree = []
	for (var i = 0; i < list.length; i++) {
		let count = delimiterCount(list[i]);

		descend(tree, list[i], count);
	}
	return tree;
}

和一些“原始”单元测试:

{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1","children":[]},{"id":"1-1-1","children":[]},{"id":"1-1-1-1","children":[]},{"id":"1-1-1-1-1"}])
let expected = [{"id":"1","children":[{"id":"1-1","children":[{"id":"1-1-1","children":[{"id":"1-1-1-1","children":[{"id":"1-1-1-1-1"}]}]}]}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1","children":[]},{"id":"1-1-1","children":[]},{"id":"1-1-1-1"}])
let expected = [{"id":"1","children":[{"id":"1-1","children":[{"id":"1-1-1","children":[{"id":"1-1-1-1"}]}]}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1","children":[]},{"id":"1-1-1"},{"id":"1-2","children":[]},{"id":"1-2-1"},{"id":"2","children":[]},{"id":"2-1"}])
let expected = [{"id":"1","children":[{"id":"1-1","children":[{"id":"1-1-1"}]},{"id":"1-2","children":[{"id":"1-2-1"}]}]},{"id":"2","children":[{"id":"2-1"}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1","children":[]},{"id":"1-1-1"},{"id":"1-2"},{"id":"2","children":[]},{"id":"2-1"}])
let expected = [{"id":"1","children":[{"id":"1-1","children":[{"id":"1-1-1"}]},{"id":"1-2"}]},{"id":"2","children":[{"id":"2-1"}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1","children":[]},{"id":"1-1-1"},{"id":"2","children":[]},{"id":"2-1"}])
let expected = [{"id":"1","children":[{"id":"1-1","children":[{"id":"1-1-1"}]}]},{"id":"2","children":[{"id":"2-1"}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1","children":[]},{"id":"1-1-1"},{"id":"2","children":[]}])
let expected = [{"id":"1","children":[{"id":"1-1","children":[{"id":"1-1-1"}]}]},{"id":"2","children":[]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1","children":[]},{"id":"1-1-1"},{"id":"1-1-2"}])
let expected = [{"id":"1","children":[{"id":"1-1","children":[{"id":"1-1-1"},{"id":"1-1-2"}]}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1","children":[]},{"id":"1-1-1"}])
let expected = [{"id":"1","children":[{"id":"1-1","children":[{"id":"1-1-1"}]}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1"},{"id":"2","children":[]},{"id":"2-1"}])
let expected = [{"id":"1","children":[{"id":"1-1"}]},{"id":"2","children":[{"id":"2-1"}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) {console.log("expected:\n" + JSON.stringify(expected, null, 2));console.log("actual:\n" + JSON.stringify(actual, null, 2))}
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1"},{"id":"1-2"}])
let expected = [{"id":"1","children":[{"id":"1-1"},{"id":"1-2"}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) console.log(JSON.stringify(actual, null, 2))
else console.log(true);
}
{
let actual = buildTree([{"id":"1","children":[]},{"id":"1-1"}])
let expected = [{"id":"1","children":[{"id":"1-1"}]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) console.log(JSON.stringify(actual, null, 2))
else console.log(true);
}
{
let actual = buildTree([{id: "1","children":[]}, {id: "2","children":[]}])
let expected = [{"id":"1","children":[]},{"id":"2","children":[]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) console.log(JSON.stringify(actual, null, 2))
else console.log(true);
}
{
let actual = buildTree([{id: "1", "children": []}])
let expected = [{"id":"1","children":[]}];
let b = JSON.stringify(actual) === JSON.stringify(expected);
if (!b) console.log(JSON.stringify(actual, null, 2))
else console.log(true);
}

Try it online!