简体   繁体   中英

Convert flat structure to hierarchical with sort by attribute

I have the same problem with Converting flat structure to hierarchical and actually it solve from the url. But I want to have the result are sort by specific field (eg: sequence field).

let items = [
    {
        id: 1,
        parentId: null,
        name: 'A',
        sequence: 1
    },
    {
        id: 4,
        parentId: 1,
        name: 'A-2',
        sequence: 2
    },
    {
        id: 5,
        parentId: 1,
        name: 'A-1',
        sequence: 1
    },
    {
        id: 2,
        parentId: null,
        name: 'B',
        sequence: 2
    }
];

result:

[
    {
        id: 1,
        parentId: null,
        name: 'A',
        sequence: 1,
        children: [
            {
                id: 5,
                parentId: 1,
                name: 'A-1',
                sequence: 1
            },
            {
                id: 4,
                parentId: 1,
                name: 'A-2',
                sequence: 2
            },
        ]
    },
    {
        id: 2,
        parentId: null,
        name: 'B',
        sequence: 2
    }
];

Is there any custom code that should I use, so I can have the result also sorted by the sequence field?

 /** * Sort an array of objects by property * @param {Array} arr Array of Objects * @param {String} p The property to sort * @param {boolean} desc Set to true for descend. sort */ const sortBy = (arr, p, desc) => arr.sort((a, b) => { if (desc) [a, b] = [b, a]; const isNum = typeof b[p] === 'number'; return (isNum? Number(a[p]) - b[p]: String(a[p]).localeCompare(b[p])); }); /** * Convert Linear Array to Tree Array * @param {Array} list to convert * @param {String} sort the property to sort */ const treefy = (list, sort) => { const map = list.reduce((m, li, i) => { m[li.id] = i; li.children = []; return m; }, {}); return list.reduce((root, li) => { const arr = li.parentId? list[map[li.parentId]].children: root; arr.push(li); if (sort) sortBy(arr, sort); return root; }, []); } // Use like: const items = [ {id:1, parentId:null, name:"B", sequence:2}, {id:4, parentId:1, name:"A-2", sequence:2}, {id:5, parentId:1, name:"A-1", sequence:1}, {id:2, parentId:null, name:"A", sequence:1} ]; const tree = treefy(items, "sequence"); console.log(tree)

You could map out the ids and then iterate through the map in order to add references into the children of some of the elements:

 let items = [{ id: 1, parentId: null, name: 'A', sequence: 1 }, { id: 4, parentId: 1, name: 'A-2', sequence: 2 }, { id: 5, parentId: 1, name: 'A-1', sequence: 1 }, { id: 2, parentId: null, name: 'B', sequence: 2 } ]; function tree(array) { let mapping = {}; array.forEach(i => { mapping[i.id] = i; // Maps out the ids }); array = []; for (let id in mapping) { let child = mapping[id]; let { parentId } = child; if (parentId) { // If there is a parent let parent = mapping[parentId]; if (.parent.children) parent;children = [child]. else parent.children;push(child). } } for (let id in mapping) { // Add to the items ONLY the parents if (.mapping[id];parentId) array.push(mapping[id]), } return array.sort((a. b) => a;id - b.id); // Make sure that the ids are in sequential order } console.log(tree(items));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM