Javascript массив заголовков для дерева - PullRequest
0 голосов
/ 26 апреля 2018

Я работаю со списком заголовков HTML (h2, h3, h4, h5, h6). Картина описывает идею: some nested headers

[
    {
        text: 'Some header',
        rank: 2, // stays for <h2>
    },
    {
        text: 'Some another header',
        rank: 3, // stays for <h3>
    },
    {
        text: 'A header with the same rank',
        rank: 3, // stays for <h3>
    },
    {
        text: 'One more subsection header',
        rank: 4, // stays for <h4>
    }
]

И я пытаюсь превратить его в дерево:

[
    {
        text: 'Some header',
        children: [
            {
                text: 'Some another header',
            },
            {
                text: 'A header with the same rank',
                children: [
                    {
                        text: 'One more subsection header',
                    }
                ]
             }
         ]
     }
]

Вот мой текущий код:

            function list_to_tree(list) {
                // We go from the end to the beggining
                list = list.reverse();

                let node, nextNode, roots = [], i;

                for (i = 0; i < list.length; i += 1) {
                    node = list[i];
                    nextNode = list[i+1];

                    // If the next one's rank is greater, the current into the next as a child
                    if (nextNode !== undefined && node.rank > nextNode.rank) {
                        list[i+1].children.push(node);
                    } else {
                    // Else it's a root
                        roots.push(node);
                    }
                }

                return roots;
            };

Но это работает только для первого h3, но второй h3 будет идти как корень. Есть идеи о том, как достичь цели? Спасибо.

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Вы можете использовать свойство уровня rank для указания вложенной позиции в массиве помощников.

Затем выполните итерацию данных и, если необходимо, создайте дочерние массивы.

function getTree(array) {
    var levels = [{}];
    array.forEach(function (o) {
        levels.length = o.rank;
        levels[o.rank - 1].children = levels[o.rank - 1].children || [];
        levels[o.rank - 1].children.push(o);
        levels[o.rank] = o;
    });
    return levels[0].children;
}

var data = [{ text: 'Main Heading', rank: 1 }, { text: 'Sub Heading', rank: 2 }, { text: 'Sub Sub Heading', rank: 3 }, { text: 'Sub Heading', rank: 2 }, { text: 'Sub Sub Heading', rank: 3 }, { text: 'Sub Sub Heading', rank: 3 }];

console.log(getTree(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 26 апреля 2018

Это решение будет работать независимо от начального ранга, а также порядка, в котором указан список ... и использует точные данные, которые вы предоставили ...

var jsonHeaders =
[
    {
        text: 'Some header',
        rank: 2, // stays for <h2>
    },
    {
        text: 'Some another header',
        rank: 3, // stays for <h3>
    },
    {
        text: 'A header with the same rank',
        rank: 3, // stays for <h3>
    },
    {
        text: 'One more subsection header',
        rank: 4, // stays for <h4>
    }
];

function list_to_tree(list)
{
    var jsonTree = [{}];
    list = list.reverse();

    for (i = 0, l = list.length; i < l; i++)
    {
        node = list[i];
        var json = {};
        json.text = node.text;
        json.rank = node.rank;
        
        if(jsonTree[0].rank == undefined)
        {
            jsonTree[0] = json;
        }
        else
        if(jsonTree[0].rank == json.rank)
        {
            jsonTree.push(json);
        }
        else
        if(jsonTree[0].rank < json.rank)
        {
            jsonTree[0] = ranker(jsonTree[0], json);
        }
        else
        if(jsonTree[0].rank > json.rank)
        {
            var jsonTemp = jsonTree[0];
            jsonTree[0]  = json;
            json         = jsonTemp;

            jsonTree[0] = ranker(jsonTree[0], json);
        }
    }
    return jsonTree;
}

function ranker(jsonTree, json)
{
    if(jsonTree.children == undefined)
    {
        jsonTree.children = [];
        jsonTree.children.push(json);
    }
    else
    if(jsonTree.children[0].rank == json.rank)
    {
        jsonTree.children.push(json);
    }
    else
    if(jsonTree.children[0].rank < json.rank)
    {
        jsonTree.children[0] = ranker(jsonTree.children[0], json);
    }
    else
    if(jsonTree.children[0].rank > json.rank)
    {
        var jsonTemp = jsonTree;
        jsonTree     = json;
        json         = jsonTemp;

        jsonTree.children[0] = ranker(jsonTree.children[0], json);
    }
    return jsonTree;
}

var jsonTree = list_to_tree(jsonHeaders);
console.log('jsonArrayTree = ', jsonTree);
0 голосов
/ 26 апреля 2018

Вот рабочая функция на тот случай, если кому-то это нужно:

            function list_to_tree(list) {
                list = list.reverse();

                let node, currentRank = list[0].rank, i, roots = [];

                for (i = 0; i < list.length; i += 1) {
                    node = list[i];

                    if (node.rank > currentRank) {

                        for (let n = i; n < list.length; n += 1) {
                            if (list[n].rank < node.rank) {
                                list[n].children.unshift(node);
                                break;
                            }
                        }


                    } else {
                        currentRank = node.rank;
                        roots.push(node);
                    }
                }

                return roots.reverse();
            };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...