JS создает дерево из набора URL - PullRequest
1 голос
/ 10 ноября 2019

У меня есть некоторые трудности при создании дерева из заданного массива URL. Основная цель - разбить URL-адреса на сегменты и расположить их в родительский-дочерний. Например, для данного массива:

   const data =  [
        {
            'id': '1',
            'name': '/home',
        },
        {
            'id': '2',
            'name': '/story',
        },
        {
            'id': '3',
            'name': '/story/summer-story',
        },
        {
            'id': '4',
            'name': '/story/summer-story/2019',
        },
    ]

Вывод должен быть:

const tree = [
    {
        'id': '1',
        'name' : '/home',
        children: []
    },
    {
        'id': '2',
        'name': '/story',
        'children': [
            {
                'id' : '3',
                'name': '/story/summer-story',
                'children': [
                    {
                        'id': '4',
                        'name': '/story/summer-story/2019'
                    }
                ]
            },
        ]
    }
]

Я уже создал какое-то решение, используя пример из Javascript, получающий Tree изнабор URL-адресов

Текущее решение, которое у меня есть, работает нормально, когда есть URL-адрес с одним или двумя сегментами. Как только он имеет более двух сегментов, он добавляет узел на корневом уровне вместо того, чтобы вложить в падающийродительский узел.

Пример кода

export const addToTree = (node, treeNodes) => {
    const parentNode = getTheParentNodeChildArray(node.name, treeNodes) || treeNodes;

    parentNode.push({
        title: node.title,
        name: node.name,
        children: []
    });
};

export const getTheParentNodeChildArray = (path, treeNodes) => {
    for (let i = 0; i < treeNodes.length; i++) {
        const treeNode = treeNodes[i];

        const lastSegment = getStringWithoutLastSegment(path);
        const lastNode = getStringWithoutLastSegment(treeNode.name);

        if (lastNode === lastSegment) {
            return treeNode.children;
        }
        else if (treeNode.children.length > 0) {
            let possibleParent = false;

            treeNode.children.forEach(function(item) {
                const lastSegmentPath = getStringWithoutLastSegment(path);
                const lastSegmentItem = getStringWithoutLastSegment(item.name);

                if (lastSegmentItem === lastSegmentPath) {
                    possibleParent = true;
                    return false;
                }
            });

            if (possibleParent) {
                return getTheParentNodeChildArray(path, treeNode.children);
            }
        }
    }
};

export const createTree = (nodes) => {
    const tree = [];

    for (let i = 0; i < nodes.length; i++) {
        const node = nodes[i];
        addToTree(node, tree);
    }
    return tree;
};

export const getStringWithoutLastSegment = (str) => {
    const stringArray = str.split('/');
    stringArray.pop();
    return (stringArray.join('/'));
};

Заранее спасибо

1 Ответ

2 голосов
/ 10 ноября 2019

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

const makeTree = data => {
  const base = {children: []};
  
  for (const node of data) {
    const path = node.name.match(/\/[^\/]+/g);
    let curr = base;
    
    path.forEach((e, i) => {
      const currPath = path.slice(0, i + 1).join("");
      const child = curr.children.find(e => e.name === currPath);
      
      if (child) {
        curr = child;
      }
      else {
        curr.children.push({
          id: node.id, name: currPath, children: []
        });
        curr = curr.children[curr.children.length-1];
      }
    });
  }
  
  return base.children;
};

const data = [
  {
    'id': '1',
    'name': '/home',
  },
  {
    'id': '2',
    'name': '/story',
  },
  {
    'id': '3',
    'name': '/story/summer-story',
  },
  {
    'id': '4',
    'name': '/story/summer-story/2019',
  },
];

console.log(makeTree(data));
...