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

Javascript 对包含与lodash或vanilla js的父/子关系的对象数组重新排序,javascript,lodash,Javascript,Lodash,我有一组对象,如: [ { id: 8, name: 'Shirts', slug: 'shirts', parent_id: null }, { id: 9, name: 'Pants', slug: 'pants', parent_id: null }, { id: 10, name: 'Vin

我有一组对象,如:

[
    {
        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中的null是否会弄乱它

编辑: 内部和外部结果也应按字母顺序排序。因此,外层的裤子先于衬衫,儿童层的棉布T恤先于复古印花。请记住,这可能是无限深的一层,棉质T恤可能是父母等等


如果每个已排序的对象都可以接收一个索引或级别,这样您就可以知道它嵌套了多少级别,那也太好了。

单个排序不起作用,因为排序数据时不考虑父子关系

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

  • 按字母对数据排序,因为以下树是按插入顺序生成的

  • 构建具有给定关系的树

  • 遍历树并返回已排序的平面数据

  • 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',parent_id:8},{id:12,name:'Business kakis',slug:'Business kakis',parent_id:9}]
    .排序(功能(a、b){
    返回a.name.localeCompare(b.name);
    }),
    树=函数(数据,根){
    var r=[],o={};
    data.forEach(函数(a){
    o[a.id]={data:a,children:o[a.id]&&o[a.id].children};
    if(a.parent_id==根){
    r、 推(o[a.id]);
    }否则{
    o[a.parent_id]=o[a.parent_id]|{};
    o[a.parent_id]。children=o[a.parent_id]。children | |[];
    o[a.parent\u id].children.push(o[a.id]);
    }
    });
    返回r;
    }(数据,空),
    排序=tree.reduce(函数遍历(r,a){
    返回r.concat(a.data,(a.children | |[])。reduce(transverse,[]);
    }, [])
    控制台日志(已排序);
    控制台日志(树)
    
    。作为控制台包装器{max height:100%!important;top:0;}
    一个部分,我尝试的内容似乎丢失了,你能在中编辑该部分吗?@Tomas,你自己尝试过解决这个问题吗?我只是在看orderBy,实际上它一定是groupBy和orderBy的混合体这很好,我希望有一个更简单的解决方案,但这是可行的。真正方便的方法是在每个结果中添加一个键,告诉你你有多少个级别。级别应该放在哪里?在每个对象上。如果它是顶层,那么它是0,如果它是根的子级,那么它是1。。。若其父对象的父对象是根对象,那个么索引是2,依此类推。