Javascript Рекурсивная функция для построения дерева - PullRequest
0 голосов
/ 01 ноября 2019

Привет, я использую JavaScript и jQuery в качестве скрипта на стороне клиента. Я немного новичок в Recursive functions. У меня есть данные JSON, как показано ниже, и я попытался создать древовидную структуру, используя данные JSON ниже, написав рекурсивную функцию, но я не могу построить древовидную структуру.

var jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }

Требуемый вывод:

var treeNode = {
                    id: 101, // random
                    text: object.name,
                    icon: "fas fa-plus",
                    subNode: {
                        // id, text, icon and subNode of Children object
                        // recursive data,  So on.... 
                    }
                };

Может кто-нибудь предложить мне или помочь мне написать javascript или jQuery Recursive function на основе данных JSON выше, чтобы я мог построить древовидную структуру. Я знаю, что прошу о помощи, потому что у меня меньше знаний о рекурсивной функции.

1 Ответ

0 голосов
/ 01 ноября 2019

Если немного абстрагироваться, довольно просто написать универсальную функцию отображения дерева. Затем мы можем предоставить две функции обратного вызова: одну для поиска дочерних узлов ввода и одну для построения выходного узла на основе ввода и сопоставленных дочерних элементов. Такая функция оказывается удивительно простой:

const mapTree = (getChildren, transformNode) => (tree) =>
  transformNode (
    tree, 
    (getChildren (tree) || []) .map (mapTree (getChildren, transformNode))
  )

Для ваших данных getChildren - это просто (node) => node._children

И преобразование узла может быть таким простым:

const transformNode = (node, children) => 
  ({
    id: node.$id,         // or a randomizing call?
    text: node.name,
    icon: "fas fa-plus",  // is this really a fixed value?
    subNode: children
  })

Сложив это вместе, мы получим

const mapTree = (getChildren, transformNode) => (tree) =>
  transformNode (
    tree, 
    (getChildren (tree) || []) .map (mapTree (getChildren, transformNode))
  )

const kids = (node) => node._children

const transformNode = (node, children) => 
  ({
    id: node.$id,
    text: node.name,
    icon: "fas fa-plus",    
    subNode: children
  })

const myTransform = mapTree (kids, transformNode)

const jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }

console .log (myTransform (jsonData))

Это немного отличается от запрошенного вами результата. Вы написали subNode: { ... }, но вместо этого я возвращаю массив объектов, subNodes: [ ... ], так как я не вижу здесь никакого реального смысла простого объекта.

Кроме того, это приведет к пустомуsubNodes массив, если входной узел не имеет дочерних элементов. Если вы предпочитаете не иметь свойства subNodes, вы можете заменить

    subNode: children

чем-то вроде

    ...(children .length ? {subNode: children} : {})

Очевидно, вам не нужны именованные помощники, и вы могли бы вызвать mapTree с анонимными функциями, такими как:

const myTransform = mapTree (
  (node) => node._children, 
  (node, children) => 
    ({
      id: node.$id,
      text: node.name,
      icon: "fas fa-plus",    
      subNode: children
    })
)

Эту функцию mapTree было очень легко написать, так как мне не нужно было думать ни о каких деталях формата вывода или ввода, как я ее написал. Но, возможно, эта абстракция мне не поможет, и я никогда не буду ее использовать, кроме как здесь. Если это так, я могу просто переработать абстрактную версию, подключив жестко закодированные обратные вызовы напрямую. Только с небольшой манипуляцией, это превратит его в эту версию:

const newTransform = (node) =>
  ({
    id: node.$id,
    text: node.name,
    icon: "fas fa-plus",    
    subNode: (node._children || []).map(newTransform)
  })

const jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }

console .log (newTransform (jsonData))

Здесь есть важный момент. Эту универсальную функцию было написать гораздо проще, чем если бы я попытался написать что-то для непосредственного преобразования вашего формата. Хотя в слишком ранней абстракции есть опасность, она также может предложить значительные преимущества. Я мог бы предпочесть оставить только эту последнюю версию, но общая абстракция упростила ее разработку.

...