按嵌套属性对对象进行分组的更优雅的方式
More elegant way to group objects by nested attribute
我正在从第三方获取数据 API,无法预先过滤。我有以下数组:
[
[
User1 {
attr1: 'abc',
attr2: ['0x1', '0xa']
},
User2 {
attr1: 'def'
attr2: ['0x1', '0xb']
}
]
[
User3 {
attr1: 'ghi',
attr2: ['0x1', '0xa']
},
User4 {
attr1: 'jkl',
attr2: ['0x1', '0xb']
},
User5 {
attr1: 'mno',
attr2: ['0x1', '0xc']
}
]
]
目标是获得以下内容。本质上,我想根据 attr2[1] 对用户进行分组,并过滤掉没有配对的用户。关键是 attr2[1].
[
{
attr2_1: '0xa',
attrs: [User1, User3]
},
{
attr2_1: '0xb',
attrs: [User2, User4]
}
]
我有一个可行的解决方案,但我想知道如何更优雅地解决它。
我按第二个属性对用户进行分组
const usersByParam = _.chain(allUsers)
.flatten()
.groupBy(user => user.attr2[1])
.value()
我过滤分组的用户以删除没有配对的条目(示例中的 User5)
const filteredUsers = _.omitBy(usersByParam, (val) => {return val.length < 2})
我通过筛选结果来获取我的用户对象
for (const key in filteredUsers) {
userArray.push({attr2_1: key, attrs: filteredUsers[key]} as User)
}
它给了我想要的东西,但我确信有更优雅的方法来解决它。
您发布的数据无效JSON。因此,假设它应该是一个对象数组,我在下面的代码中对其进行了修改以反映这一点。
我不确定如何在 lodash 中执行此操作,但您可以使用 vanilla JavaScript 来完成此操作。通过使用 Array.reduce() and Array.filter() 方法,您可以根据需要操作数据。
请参阅下面的代码段。
const data = [{
User1: {
attr1: 'abc',
attr2: ['0x1', '0xa']
}
},
{
User2: {
attr1: 'def',
attr2: ['0x1', '0xb']
}
},
{
User3: {
attr1: 'ghi',
attr2: ['0x1', '0xa']
}
},
{
User4: {
attr1: 'jkl',
attr2: ['0x1', '0xb']
}
},
{
User5: {
attr1: 'mno',
attr2: ['0x1', '0xc']
}
}
];
const reduced = Object.values(data.reduce((a, c) => {
var user = Object.keys(c)[0];
var key = c[user].attr2[1];
a[key] ??= {};
a[key].attr2_1 = key;
a[key].attrs ??= [];
a[key].attrs.push(user);
return a;
}, {})).filter(element => element.attrs.length === 2);
console.log(reduced);
您可以使用 JavaScript:
const data = [{User1: {attr1: 'abc',attr2: ['0x1', '0xa']}},{User2: {attr1: 'def',attr2: ['0x1', '0xb']}},{User3: {attr1: 'ghi',attr2: ['0x1', '0xa']}},{User4: {attr1: 'jkl',attr2: ['0x1', '0xb']}},{User5: {attr1: 'mno',attr2: ['0x1', '0xc']}}]
const result = Object.entries(
data.reduce((a, c) => {
const [k] = Object.keys(c)
a[c[k].attr2[1]] = [...(a[c[k].attr2[1]] || []), k]
return a
}, {})
)
.filter(([, users]) => users.length > 1)
.map(([attr2_1, attrs]) => ({ attr2_1, attrs }))
console.log(result)
您的代码已经很优雅了,我只是将 for ... in
替换为 map
const userArray = _.chain(allUsers)
.flatten()
.groupBy(user => user.attr2[1])
.omitBy(val => val.length < 2)
.map((attrs, attr2_1) => ({ attr2_1, attrs }))
.value();
我正在从第三方获取数据 API,无法预先过滤。我有以下数组:
[
[
User1 {
attr1: 'abc',
attr2: ['0x1', '0xa']
},
User2 {
attr1: 'def'
attr2: ['0x1', '0xb']
}
]
[
User3 {
attr1: 'ghi',
attr2: ['0x1', '0xa']
},
User4 {
attr1: 'jkl',
attr2: ['0x1', '0xb']
},
User5 {
attr1: 'mno',
attr2: ['0x1', '0xc']
}
]
]
目标是获得以下内容。本质上,我想根据 attr2[1] 对用户进行分组,并过滤掉没有配对的用户。关键是 attr2[1].
[
{
attr2_1: '0xa',
attrs: [User1, User3]
},
{
attr2_1: '0xb',
attrs: [User2, User4]
}
]
我有一个可行的解决方案,但我想知道如何更优雅地解决它。
我按第二个属性对用户进行分组
const usersByParam = _.chain(allUsers)
.flatten()
.groupBy(user => user.attr2[1])
.value()
我过滤分组的用户以删除没有配对的条目(示例中的 User5)
const filteredUsers = _.omitBy(usersByParam, (val) => {return val.length < 2})
我通过筛选结果来获取我的用户对象
for (const key in filteredUsers) {
userArray.push({attr2_1: key, attrs: filteredUsers[key]} as User)
}
它给了我想要的东西,但我确信有更优雅的方法来解决它。
您发布的数据无效JSON。因此,假设它应该是一个对象数组,我在下面的代码中对其进行了修改以反映这一点。
我不确定如何在 lodash 中执行此操作,但您可以使用 vanilla JavaScript 来完成此操作。通过使用 Array.reduce() and Array.filter() 方法,您可以根据需要操作数据。
请参阅下面的代码段。
const data = [{
User1: {
attr1: 'abc',
attr2: ['0x1', '0xa']
}
},
{
User2: {
attr1: 'def',
attr2: ['0x1', '0xb']
}
},
{
User3: {
attr1: 'ghi',
attr2: ['0x1', '0xa']
}
},
{
User4: {
attr1: 'jkl',
attr2: ['0x1', '0xb']
}
},
{
User5: {
attr1: 'mno',
attr2: ['0x1', '0xc']
}
}
];
const reduced = Object.values(data.reduce((a, c) => {
var user = Object.keys(c)[0];
var key = c[user].attr2[1];
a[key] ??= {};
a[key].attr2_1 = key;
a[key].attrs ??= [];
a[key].attrs.push(user);
return a;
}, {})).filter(element => element.attrs.length === 2);
console.log(reduced);
您可以使用 JavaScript:
const data = [{User1: {attr1: 'abc',attr2: ['0x1', '0xa']}},{User2: {attr1: 'def',attr2: ['0x1', '0xb']}},{User3: {attr1: 'ghi',attr2: ['0x1', '0xa']}},{User4: {attr1: 'jkl',attr2: ['0x1', '0xb']}},{User5: {attr1: 'mno',attr2: ['0x1', '0xc']}}]
const result = Object.entries(
data.reduce((a, c) => {
const [k] = Object.keys(c)
a[c[k].attr2[1]] = [...(a[c[k].attr2[1]] || []), k]
return a
}, {})
)
.filter(([, users]) => users.length > 1)
.map(([attr2_1, attrs]) => ({ attr2_1, attrs }))
console.log(result)
您的代码已经很优雅了,我只是将 for ... in
替换为 map
const userArray = _.chain(allUsers)
.flatten()
.groupBy(user => user.attr2[1])
.omitBy(val => val.length < 2)
.map((attrs, attr2_1) => ({ attr2_1, attrs }))
.value();