使用键和值数组将对象的 javascript 数组转换为对象



我有一个对象数组,我需要转换为新对象。 一些值作为键和一个值数组。

const data = [
{
type: 'user',
id: 1
},
{
type: 'user',
id: 2
},
{
type: 'group',
id: 1
},
{
type: 'group',
id: 2
},
{
type: 'user',
id: 3
},
{
type: 'user',
id: 4
}
]

期望的结果是

const result = {
user: [1, 2, 3, 4],
group: [1, 2]
}

我尝试使用reduced但不是我期望的。

const result = data.reduce((acc, { type, ...obj }) => {
acc[type] = data.map(item => item.id)
return acc;
}, {})
result = { user: [ 1, 2, 1, 2, 3, 4 ], group: [ 1, 2, 1, 2, 3, 4 ] }

每次迭代,你检查累加对象是否具有类型,如果是,则将迭代元素的 id 推送到现有数组,否则初始化数组

const data = [
{
type: "user",
id: 1,
},
{
type: "user",
id: 2,
},
{
type: "group",
id: 1,
},
{
type: "group",
id: 2,
},
{
type: "user",
id: 3,
},
{
type: "user",
id: 4,
},
]
const res = data.reduce((acc, el) => {
if (acc[el.type]) {
acc[el.type].push(el.id)
} else {
acc[el.type] = [el.id]
}
return acc
}, {})
console.log(res)

除非你使用预定义的化简器函数进行函数式编程,否则reduce通常是一个过于复杂的工具。只需使用循环。

在这种情况下,您将从一个具有usergroup属性的对象开始,这些属性具有空数组,然后使用动态属性名称添加到正确的数组:

const result = { user: [], group: [] };
for (const {type, id} of data) {
result[type].push(id);
}

现场示例:

const data = [
{
type: 'user',
id: 1
},
{
type: 'user',
id: 2
},
{
type: 'group',
id: 1
},
{
type: 'group',
id: 2
},
{
type: 'user',
id: 3
},
{
type: 'user',
id: 4
}
];
const result = { user: [], group: [] };
for (const {type, id} of data) {
result[type].push(id);
}
console.log(result);

如果事先不知道type值,请动态添加数组:

const result = { user: [], group: [] };
for (const {type, id} of data) {
if (!result[type]) {
result[type] = [];
}
result[type].push(id);
}

现场示例:

const data = [
{
type: 'user',
id: 1
},
{
type: 'user',
id: 2
},
{
type: 'group',
id: 1
},
{
type: 'group',
id: 2
},
{
type: 'user',
id: 3
},
{
type: 'user',
id: 4
}
];
const result = { user: [], group: [] };
for (const {type, id} of data) {
if (!result[type]) {
result[type] = [];
}
result[type].push(id);
}
console.log(result);

如果你喜欢非常简洁,你可以使用新的??=运算符在数组还没有的时候添加数组(对我来说,在这种情况下,它走得太远了,失去了清晰度):

const result = { user: [], group: [] };
for (const {type, id} of data) {
(result[type] ??= []).push(id);
}

现场示例:

const data = [
{
type: 'user',
id: 1
},
{
type: 'user',
id: 2
},
{
type: 'group',
id: 1
},
{
type: 'group',
id: 2
},
{
type: 'user',
id: 3
},
{
type: 'user',
id: 4
}
];
const result = { user: [], group: [] };
for (const {type, id} of data) {
(result[type] ??= []).push(id);
}
console.log(result);


你可以把它硬塞进一个reduce(因为你可以把任何数组操作硬塞进一个reduce),但这样做并不能给你带来任何东西。这是第一个使用reduce而不是循环:

const result = data.reduce((acc, {type, id}) => {
acc[type].push(id);
return acc;
}, {user: [], group: []});

const data = [
{
type: 'user',
id: 1
},
{
type: 'user',
id: 2
},
{
type: 'group',
id: 1
},
{
type: 'group',
id: 2
},
{
type: 'user',
id: 3
},
{
type: 'user',
id: 4
}
];
const result = data.reduce((acc, {type, id}) => {
acc[type].push(id);
return acc;
}, {user: [], group: []});
console.log(result);

您需要检查该属性是否存在并向其推送id

const
data = [{ type: 'user', id: 1 }, { type: 'user', id: 2 }, { type: 'group', id: 1 }, { type: 'group', id: 2 }, { type: 'user', id: 3 }, { type: 'user', id: 4 }],
result = data.reduce((acc, { type, id }) => {
acc[type] ??= [];
acc[type].push(id);
return acc;
}, {});
console.log(result);

如果累加器上不存在该属性,请添加它,并且如果它确实将id推送到其中:

const data = [{"type":"user","id":1},{"type":"user","id":2},{"type":"group","id":1},{"type":"group","id":2},{"type":"user","id":3},{"type":"user","id":4}];
const result = data.reduce((acc, { type, id }) => {
if(!acc[type]) acc[type] = [];

acc[type].push(id);
return acc;
}, {})
console.log(result)

这个怎么样?

groupBy()的香草版本

const groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x.id);
return rv;
}, {});
};

您可以使用以下方法通过键轻松调用组:

const result = groupBy(data, 'type');

完整代码:

const groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x.id);
return rv;
}, {});
};
const data = [
{
type: 'user',
id: 1
},
{
type: 'user',
id: 2
},
{
type: 'group',
id: 1
},
{
type: 'group',
id: 2
},
{
type: 'user',
id: 3
},
{
type: 'user',
id: 4
}
]
const result = groupBy(data, 'type');
console.log(result); // { group: [1, 2], user: [1, 2, 3, 4] }

参考链接。

这是一个使用Object.fromEntries为结果对象构建框架的解决方案(使用空数组)。然后,一个简单的循环可以填充这些数组,你就完成了:

let data = [{ type: 'user', id: 1 }, { type: 'user', id: 2 }, { type: 'group', id: 1 }, { type: 'group', id: 2 }, { type: 'user', id: 3 }, { type: 'user', id: 4 }];
let result = Object.fromEntries(data.map(({type}) => [type, []]));
for (let {type, id} of data) result[type].push(id);
console.log(result);

最新更新