Javascript 减少包含几乎相同对象的数组

Javascript 减少包含几乎相同对象的数组,javascript,arrays,lodash,Javascript,Arrays,Lodash,我试图找到一种高效且尽可能短的方法,将数组中几乎相同的对象折叠为包含其自身数组和不相同数据的对象。当我试图解释它时,它听起来很复杂,让我告诉你我的意思: 我有一个如下所示的对象数组: [{ id: '6b6574cf-d77a-4ed8-852f-cb60a0d377cd', first_name: 'SomeName', email: 'some@email.com', rName: 'User',

我试图找到一种高效且尽可能短的方法,将数组中几乎相同的对象折叠为包含其自身数组和不相同数据的对象。当我试图解释它时,它听起来很复杂,让我告诉你我的意思:

我有一个如下所示的对象数组:

    [{ 
        id: '6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
        first_name: 'SomeName',
        email: 'some@email.com',
        rName: 'User',                                // 0,1
        rAuthority: 'ROLE_USER',                      // 0,1
        pId: 'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
        pMobile: '012 345 6789',
        atId: '90db0c5d-3030-44aa-9dc0-40242af0d5c5', // 0,2
        atPlatform: 'web',
    },{ 
        id: '6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
        first_name: 'SomeName',
        email: 'some@email.com',
        rName: 'User',                                // 0,1
        rAuthority: 'ROLE_USER',                      // 0,1
        pId: 'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
        pMobile: '012 345 6789',
        atId: 'e7d53cab-a9b9-40ae-9271-11d79c2f269c', // 1,3
        atPlatform: 'web',
    },{ 
        id: '6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
        first_name: 'SomeName',
        email: 'some@email.com',
        rName: 'Admin',                               // 2,3
        rAuthority: 'ROLE_ADMIN',                     // 2,3
        pId: 'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
        pMobile: '012 345 6789',
        atId: '90db0c5d-3030-44aa-9dc0-40242af0d5c5', // 0,2
        atPlatform: 'web',
    },{ 
        id: '6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
        first_name: 'SomeName',
        email: 'some@email.com',
        rName: 'Admin',                               // 2,3
        rAuthority: 'ROLE_ADMIN',                     // 2,3
        pId: 'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
        pMobile: '012 345 6789',
        atId: 'e7d53cab-a9b9-40ae-9271-11d79c2f269c', // 1,3
        atPlatform: 'web',
    }]

// I point out which of the properties are not identical by adding 
// quotes showing which indices of the array contains unique values of 
// said property. If the there's not a quote to the right of the 
// property it's identical across all indices.
我想将这个数组转换成一个数组,其中具有重复ID的对象被折叠成一个具有包含不相同数据的对象数组的对象。看起来是这样的:

[{
    id: '6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
    first_name: 'SomeName',
    email: 'some@email.com',
    roles: [{
            name: 'User',
            authority: 'ROLE_USER'
    },{
            name: 'Admin',
            authority: 'ROLE_ADMIN'
    }],
    profiles: [{
            id: 'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
            mobile: '012 345 6789',
    }],
    tokens: [{
            id: '90db0c5d-3030-44aa-9dc0-40242af0d5c5',
            platform: 'web',
    },{
            id: 'e7d53cab-a9b9-40ae-9271-11d79c2f269c',
            platform: 'web',
    }]
}]
如您所见,先前数组中所有前缀为
r
的属性现在都在
角色
属性的数组中具有自己的对象
p
前缀属性位于
配置文件中
at
前缀属性位于
令牌中
。如果一个对象与另一个对象具有相同的
id
,则该对象被视为“相同”

下面是我编写的一些代码,它们似乎成功地将第一个数组转换为第二个数组:

...then(data => {

    let users = [];

    // gets the correct formatting
    data.forEach((d, i) => {
        let found = false;
        users.forEach((u, j) => {
            if(d.id === u.id) {
                u.roles.push({ name:d.rName, authority:d.rAuthority });
                u.tokens.push({ id:d.atId, platform:d.atPlatform });
                u.profiles.push({ id:d.pId, mobile:d.pMobile });
                found = true;
            }
        });
        if(!found) {
            users.push({
                id:d.id,
                first_name:d.first_name,
                email:d.email,
                roles: [{ name:d.rName, authority:d.rAuthority }],
                profiles: [{ id:d.pId, mobile:d.pMobile }],
                tokens: [{ id:d.atId, platform:d.atPlatform }]
            });
        }
    });

    // remove duplicates from sub-arrays
    users.forEach((user, i) => {
        user.roles = _.uniqBy(user.roles, 'name');
        user.profiles = _.uniqBy(user.profiles, 'id');
        user.tokens = _.uniqBy(user.tokens, 'id');
    });
});
这个代码有两个问题。第一个是它非常长(为了这个问题,我实际上从第一个数组中删除了许多属性-实际上,每个对象的属性数量都是您在这里看到的两倍多,这使得代码更长),第二个是我强烈怀疑它可能非常低效

问题:

有人能帮我重写我用来格式化数组的代码,使之变得更短、更高效吗。我确实安装了,所以我更喜欢使用它的答案,但我也很乐意接受vanilla.js答案

附加说明:


这个问题是我发布的后续问题。看这个问题会模糊地告诉你我在这个问题中试图转换的数据来自哪里。简短的版本是它来自数据库,这是我使用Knex.js延迟加载的想法。其思想是,每个用户都可以有多个角色、配置文件和身份验证令牌。

您可以使用一个reducer并构建新的对象数组:

const输入=[{
id:'6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
名字:“SomeName”,
电邮:'some@email.com',
rName:'用户',//0,1
rAuthority:'ROLE_USER',//0,1
pId:'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
pMobile:'0123456789',
atId:'90db0c5d-3030-44aa-9dc0-40242af0d5c5',/0,2
atPlatform:'web',
}, {
id:'6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
名字:“SomeName”,
电邮:'some@email.com',
rName:'用户',//0,1
rAuthority:'ROLE_USER',//0,1
pId:'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
pMobile:'0123456789',
atId:'e7d53cab-a9b9-40ae-9271-11d79c2f269c',/1,3
atPlatform:'web',
}, {
id:'6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
名字:“SomeName”,
电邮:'some@email.com',
rName:'Admin',/2,3
rAuthority:'ROLE_ADMIN',//2,3
pId:'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
pMobile:'0123456789',
atId:'90db0c5d-3030-44aa-9dc0-40242af0d5c5',/0,2
atPlatform:'web',
}, {
id:'6b6574cf-d77a-4ed8-852f-cb60a0d377cd',
名字:“SomeName”,
电邮:'some@email.com',
rName:'Admin',/2,3
rAuthority:'ROLE_ADMIN',//2,3
pId:'e7da65a9-ea2d-4c77-82f6-e1addc78fb6e',
pMobile:'0123456789',
atId:'e7d53cab-a9b9-40ae-9271-11d79c2f269c',/1,3
atPlatform:'web',
}];
console.log(input.reduce)(acc、val、ind)=>{
如果(!acc.find(el=>el.id==val.id)){
加速推({
id:val.id,
名字:val.first_name,
电子邮件:val.email,
角色:[],
简介:[],
代币:[]
});
}
否则{
const el=acc.find(el=>el.id==val.id);
if(!el.roles.find(a=>a.authority==val.rAuthority)){
推({
授权:val.rAuthority,
姓名:val.rName
});
}
如果(!el.profiles.find(a=>a.id==val.pId)){
推({
id:val.pId,
移动电话:val.pMobile
});
}
如果(!el.tokens.find(a=>a.id==val.atId)){
el.tokens.push({
id:val.atId,
站台:val.atPlatform
});
}
}
返回acc;

}, []));与Quirimo的答案略有不同的方法,使用对象作为中间值将每个项/子项映射到其相应的标识符,然后使用将其还原回:

const输入=[
{id:'6b6574cf-d77a-4ed8-852f-cb60a0d377cd',名字:'SomeName',电子邮件:'some@email.com,rName:“用户”,RAUTORITY:“角色用户”,pId:“e7da65a9-ea2d-4c77-82f6-e1addc78fb6e”,pMobile:“012 345 6789”,atId:“90db0c5d-3030-44aa-9dc0-4024AF0D5C5”,atPlatform:“web”,
{id:'6b6574cf-d77a-4ed8-852f-cb60a0d377cd',名字:'SomeName',电子邮件:'some@email.com,rName:“用户”,RAUTORITY:“角色用户”,pId:“e7da65a9-ea2d-4c77-82f6-e1addc78fb6e”,pMobile:“012 345 6789”,atId:“e7d53cab-a9b9-40ae-9271-11d79c2f269c”,atPlatform:“web”},
{id:'6b6574cf-d77a-4ed8-852f-cb60a0d377cd',名字:'SomeName',电子邮件:'some@email.com,rName:“管理”,RAUTORITY:“角色管理”,pId:“e7da65a9-ea2d-4c77-82f6-e1addc78fb6e”,pMobile:“012 345 6789”,atId:“90db0c5d-3030-44aa-9dc0-4024AF0D5C5”,atPlatform:“web”,
{id:'6b6574cf-d77a-4ed8-852f-cb60a0d377cd',名字:'SomeName',电子邮件:'some@email.com,rName:“管理”,RAUTORITY:“角色管理”,pId:“e7da65a9-ea2d-4c77-82f6-e1addc78fb6e”,pMobile:“012 345 6789”,atId:“e7d53cab-a9b9-40ae-9271-11d79c2f269c”,atPlatform:“web”}
];
const result=Object.values(input.reduce)(结果,项)=>{
如果(!(结果中的item.id)){
结果[item.id]={id:item.id,first_name:item.first_name,email:item.email,角色:{},配置文件:{},令牌:{};
}
结果[item.id]。角色[item.rName]={name:item.rName,权限:item.rAuthority};
结果[item.id].profiles[item.pId]={id:item.pId,mobile:item.pMobile};
结果[item.id]。令牌[item.atId]={id:item.atId,platf