使用lodash或vanilla js重新排序包含父/子关系的对象数组

时间:2017-12-09 08:12:41

标签: javascript lodash

我有一系列对象,如:

[
    {
        id: 8,
        name: 'Shirts',
        slug: 'shirts',
        parent_id: null
    },
    {
        id: 9,
        name: 'Pants',
        slug: 'pants',
        parent_id: null
    },
    {
        id: 10,
        name: 'Vintage Prints',
        slug: 'vintage-prints',
        parent_id: 8
    },
    {
        id: 11,
        name: 'Cotton Tee',
        slug: 'cotton-tee',
        parent_id: 8
    },
    {
        id: 12,
        name: 'Business Khakis',
        slug: 'business-khakis',
        parent_id: 9
    }
]

我需要的是:

[
    {
        id: 9,
        name: 'Pants',
        slug: 'pants',
        parent_id: null
    },
    {
        id: 12,
        name: 'Business Khakis',
        slug: 'business-khakis',
        parent_id: 9
    },
    {
        id: 8,
        name: 'Shirts',
        slug: 'shirts',
        parent_id: null
    },
    {
        id: 11,
        name: 'Cotton Tee',
        slug: 'cotton-tee',
        parent_id: 8
    },
    {
        id: 10,
        name: 'Vintage Prints',
        slug: 'vintage-prints',
        parent_id: 8
    }
]

我做了什么: 这看起来应该有效:

_.orderBy(categories, ['parent_id', 'name'], ['asc', 'asc']);

但是我想知道parent_id中的空值是否正在弄乱它。

修改 内部和外部结果也应按字母顺序排序。所以裤子在外层衬衫之前和Cotton Tee之前的Vintage Tints在儿童层。请记住,这可能是无限层,棉花Tee可能是父母等等。

如果每个已排序的对象都可以接收索引或级别,以便您知道它嵌套了多少级别,那也很棒。

1 个答案:

答案 0 :(得分:0)

单一排序不起作用,因为父子关系在排序数据时不予考虑。

此解决方案分为三个部分:

  1. 按字母顺序对数据进行排序,因为以下树是按插入顺序构建的。

  2. 使用给定的关系构建树。

  3. 遍历树并获取已排序的平面数据。

  4. var data = [{ id: 8, name: 'Shirts', slug: 'shirts', parent_id: null }, { id: 9, name: 'Pants', slug: 'pants', parent_id: null }, { id: 10, name: 'Vintage Prints', slug: 'vintage-prints', parent_id: 8 }, { id: 11, name: 'Cotton Tee', slug: 'cotton-tee', parent_id: 8 }, { id: 12, name: 'Business Khakis', slug: 'business-khakis', parent_id: 9 }]
        .sort(function (a, b) {
            return a.name.localeCompare(b.name);
        }),
        tree = function (data, root) {
            var r = [], o = {};
            data.forEach(function (a) {
                o[a.id] = { data: a, children: o[a.id] && o[a.id].children };
                if (a.parent_id === root) {
                    r.push(o[a.id]);
                } else {
                    o[a.parent_id] = o[a.parent_id] || {};
                    o[a.parent_id].children = o[a.parent_id].children || [];
                    o[a.parent_id].children.push(o[a.id]);
                }
            });
            return r;
        }(data, null),
        sorted = tree.reduce(function traverse(r, a) {
            return r.concat(a.data, (a.children || []).reduce(traverse, []));
        }, [])
    
    console.log(sorted);
    console.log(tree);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    具有级别的扩展版本:

    var data = [{ id: 8, name: 'Shirts', slug: 'shirts', parent_id: null }, { id: 9, name: 'Pants', slug: 'pants', parent_id: null }, { id: 10, name: 'Vintage Prints', slug: 'vintage-prints', parent_id: 8 }, { id: 11, name: 'Cotton Tee', slug: 'cotton-tee', parent_id: 8 }, { id: 12, name: 'Business Khakis', slug: 'business-khakis', parent_id: 9 }]
        .sort(function (a, b) {
            return a.name.localeCompare(b.name);
        }),
        tree = function (data, root) {
            var r = [], o = {};
            data.forEach(function (a) {
                o[a.id] = { data: a, children: o[a.id] && o[a.id].children };
                if (a.parent_id === root) {
                    r.push(o[a.id]);
                } else {
                    o[a.parent_id] = o[a.parent_id] || {};
                    o[a.parent_id].children = o[a.parent_id].children || [];
                    o[a.parent_id].children.push(o[a.id]);
                }
            });
            return r;
        }(data, null),
        sorted = tree.reduce(function traverse(level) {
            return function (r, a) {
                a.data.level = level
                return r.concat(a.data, (a.children || []).reduce(traverse(level + 1), []));
            };
        }(0), []);
    
    console.log(sorted);
    .as-console-wrapper { max-height: 100% !important; top: 0; }