从 PHP 中的二维数组创建非二叉树

Creating a non-binary tree from a two-dimensional array in PHP

我正在尝试根据存储在二维数组中的值设置由 KendoUI 提供的 Treeview。不幸的是,我无法全神贯注于数据源的创建,它应该是 JavaScript.

中使用的多维数组

方案是递归读取二维数组,将PHP中的数据源逐条构造为字符串,然后传递给JavaScript函数

二维数组示例: (1维中的key是父元素的'name'; 子元素的键是一个整数,值为子元素的 'name')

Array
(
    [1] => Array
        (
            [0] => 2
            [1] => 3
            [2] => 4
        )

    [2] => Array
        (
            [0] => 3
        )

    [3] => Array
        (
            [0] => 3
            [1] => 1
        )
    [4] => Array
        (
            [0] => 2
        )
)

它应该是什么样子的一个例子(有两个值):

  dataSource: [
    { text: "1", items: [
      { text: "2", items: [
        { text: "3" }
        ]},
      { text: "3" , items: [
        { text: "3" },
        { text: "1" }
        ]},
      { text: "4", items: [
        { text: "2", items: [
          { text: "3", items: [
            { text: "3" },
              { text: "1" }
            ] }
          ] }
        ] }
     ] },
    { text: "2", items: [
      { text: "3", items: [
        { text: "3" },
        { text: "1" , items: [
          { text: "1" },
          { text: "3" },
            { text: "4", items: [
              { text: "2" }
        ] }
          ] }
        ] }
     ] }
  ]

我知道我必须考虑算法中的无限循环。从树的 'leaf' 到 'root' a 的直接路径最多只能包含单个值的 2 个实例。 如果满足该条件,则分支将被放弃,不应再进一步填充。

任何人都可以给我一些正确方向的指示吗? 有什么 PHP class 可以用来简化这个问题吗?

如果您想将 PHP 结构转换为简单的 JS 映射,那么您可以在 JS 中使用类似这样的东西来创建您的结构:

const makeTree = (data, nodes = [...data .keys ()], path = []) => { 
  const res = nodes
    .filter ((id) => path .filter (x => x == id) .length < 2)
    .map((id) => {
      const kids = makeTree(data, data .get (id), path .concat (id));
      return {
        text: id,
        ...(kids .length ? {items: kids} : {})
      }
    })
    return res
}

const data = new Map([
  ['1', ['2', '3', '4']],
  ['2', ['3']],
  ['3', ['3', '1']],
  ['4', ['2']]
])


console .log (
  makeTree (data) 
)

makeTree 接受一个像上面那样的 Map,一个包含分支值列表的数组,以及一个包含当前路径的数组。初始调用将分支值默认为 Map 的键,并将路径默认为空数组。后续调用通过在地图中查找当前值并将该值附加到路径来计算节点。

我发现在生成的对象中也包含 path 有助于调试:

      return {
        text: id,
        path: path.join('') + id,
        ...(kids .length ? {items: kids} : {})
      }

配合合适的display函数,可以分层查看输出:

/*

1                                       (1)
...2                                    (12)
.......3                                (123)
...........3                            (1233)
...............1                        (12331)
...................2                    (123312)
...................4                    (123314)
.......................2                (1233142)
...........1                            (1231)
...............2                        (12312)
...................3                    (123123)
...............3                        (12313)
...............4                        (12314)
...................2                    (123142)
.......................3                (1231423)
...3                                    (13)
.......3                                (133)
...........1                            (1331)
...............2                        (13312)
...............4                        (13314)
...................2                    (133142)
.......1                                (131)
...........2                            (1312)
...............3                        (13123)
...........3                            (1313)
...........4                            (1314)
...............2                        (13142)
...................3                    (131423)
...4                                    (14)
.......2                                (142)
...........3                            (1423)
...............3                        (14233)
...................1                    (142331)
.......................2                (1423312)
.......................4                (1423314)
...........................2            (14233142)
...............1                        (14231)
...................2                    (142312)
.......................3                (1423123)
...................3                    (142313)
...................4                    (142314)
.......................2                (1423142)
...........................3            (14231423)
2                                       (2)
...3                                    (23)
.......3                                (233)
...........1                            (2331)
...............2                        (23312)
...............4                        (23314)
...................2                    (233142)
.......1                                (231)
...........2                            (2312)
...............3                        (23123)
...................1                    (231231)
.......................4                (2312314)
...........3                            (2313)
...............1                        (23131)
...................2                    (231312)
...................4                    (231314)
.......................2                (2313142)
...........4                            (2314)
...............2                        (23142)
...................3                    (231423)
.......................1                (2314231)
...........................4            (23142314)
3                                       (3)
...3                                    (33)
.......1                                (331)
...........2                            (3312)
...........4                            (3314)
...............2                        (33142)
...1                                    (31)
.......2                                (312)
...........3                            (3123)
...............1                        (31231)
...................2                    (312312)
...................4                    (312314)
.......................2                (3123142)
.......3                                (313)
...........1                            (3131)
...............2                        (31312)
...............4                        (31314)
...................2                    (313142)
.......4                                (314)
...........2                            (3142)
...............3                        (31423)
...................1                    (314231)
.......................2                (3142312)
.......................4                (3142314)
...........................2            (31423142)
4                                       (4)
...2                                    (42)
.......3                                (423)
...........3                            (4233)
...............1                        (42331)
...................2                    (423312)
...................4                    (423314)
.......................2                (4233142)
...........1                            (4231)
...............2                        (42312)
...................3                    (423123)
.......................1                (4231231)
...........................4            (42312314)
...............3                        (42313)
...................1                    (423131)
.......................2                (4231312)
.......................4                (4231314)
...........................2            (42313142)
...............4                        (42314)
...................2                    (423142)
.......................3                (4231423)
...........................1            (42314231)

*/

如果您确实希望输入值是数字,text 节点是字符串,您可以在生成的对象中将 id 包装为 String(id)

此代码依赖于每个映射值中的每个条目作为映射中的键。我不知道如果不这样做会发生什么。据我所知,它会除以零,发射核导弹,并偷走你的男朋友,所以要小心!