我有以下对象数组:
[
{
"id": 1,
"price": 22,
"from": "00:00:00",
"to": "02:00:00"
},
{
"id": 1,
"price": 23,
"from": "02:00:00",
"to": "04:00:00"
},
{
"id": 2,
"price": 10,
"from": "04:00:00",
"to": "1.00:00:00"
}
]
我需要对它进行重组,这样它就可以按ID组合对象,并创建一个新的嵌套对象数组:
[
{
"id": 1,
"prices": [
{
"price": 22,
"from": "00:00:00",
"to": "02:00:00"
},
{
"price": 23,
"from": "02:00:00",
"to": "04:00:00"
},
]
}
{
"id": 2,
"prices": [
{
"price": 10,
"from": "04:00:00",
"to": "1.00:00:00"
}
]
}
]
有简单的方法吗?我在分裂中迷路了,forEach和地图。谢谢
一种方法是使用Map
来收集每个id的价格。首先为每个id关联一个空的价格列表,然后迭代数据以填充这些数组,最后提取Map
值以获得结果:
const data = [{"id": 1,"price": 22,"from": "00:00:00","to": "02:00:00"},{"id": 1,"price": 23,"from": "02:00:00","to": "04:00:00"},{"id": 2,"price": 10,"from": "04:00:00","to": "1.00:00:00"}];
const map = new Map(data.map(({id}) => [id, { id, prices: [] }]));
for (const {id, ...rest} of data) map.get(id).prices.push(rest);
const result = [...map.values()];
console.log(result);
通过散列分组可以避免调用.find()
或.findIndex()
const data=[{id:1,price:22,from:"00:00:00",to:"02:00:00"},{id:1,price:23,from:"02:00:00",to:"04:00:00"},{id:2,price:10,from:"04:00:00",to:"1.00:00:00"}];
const result = Object.values(data.reduce((acc, { id, ...rest }) => {
acc[id] ??= { id, prices: [] };
acc[id].prices.push(rest);
return acc;
}, {}));
console.log(result);
.as-console-wrapper {max-height: 100% !important; top: 0}
您可以将Array.reduce方法与Array.findIndex一起使用来转换数据。
const data = [{
"id": 1,
"price": 22,
"from": "00:00:00",
"to": "02:00:00"
},
{
"id": 1,
"price": 23,
"from": "02:00:00",
"to": "04:00:00"
},
{
"id": 2,
"price": 10,
"from": "04:00:00",
"to": "1.00:00:00"
}
];
const transformedData = data.reduce((acc, item) => {
const priceData = {
price: item.price,
to: item.to,
from: item.from,
};
const index = acc.findIndex(({
id
}) => id === item.id);
if (index === -1) {
return [
...acc,
{
id: item.id,
prices: [
priceData
]
},
];
} else {
acc[index].prices.push(priceData);
return acc;
}
}, []);
console.log(transformedData);
const items = [
{
"id": 1,
"price": 22,
"from": "00:00:00",
"to": "02:00:00"
},
{
"id": 1,
"price": 23,
"from": "02:00:00",
"to": "04:00:00"
},
{
"id": 2,
"price": 10,
"from": "04:00:00",
"to": "1.00:00:00"
}
]
const result = items
.map(i => i.id)
.filter((item, pos, self) => self.indexOf(item) == pos)
.map( i => ({
id : i,
prices : items
.filter(item => item.id === i)
.map(({ price, from, to}) => ({price, from , to}) )
}) )
console.log(result)
是的,有一种简单的方法可以使用reduce()
。
const input = [
{
id: 1,
price: 22,
from: "00:00:00",
to: "02:00:00",
},
{
id: 1,
price: 23,
from: "02:00:00",
to: "04:00:00",
},
{
id: 2,
price: 10,
from: "04:00:00",
to: "1.00:00:00",
},
];
const output = input.reduce((nested, cur) => {
const objWithoutId = (({id, ...o}) => o)(cur);
if (!nested[cur.id]) {
nested[cur.id] = {
id: cur.id,
prices: [objWithoutId]
};
}
else nested[cur.id].prices.push(objWithoutId);
return nested;
}, {});
console.log(Object.values(output));
.as-console-wrapper { max-height: 100% !important; top: 0; }
解释
我们使用JavaScript对象对输入进行循环。对于每个对象,我们都会检查它的ID。当我们的对象中还没有存储该ID时,我们会创建一个新对象,其中包含id
和prices
数组以及当前值(没有id
属性)。如果我们已经遇到了相同的id
,我们只需要将当前值(不带id
属性)推送到已经存在的数组。
由于我们只有一个循环,查找需要O(1)
时间,因此该算法需要O(n)
才能给出有效结果。
使用这个一行
const objWithoutId = (({id, ...o}) => o)(cur);
我们创建了一个新的对象,它包含除CCD_ 13之外的所有属性。
Lat,但同样重要的是,我们只需要使用Object.values()
获取创建的JavaScript对象的值。您也可以使用Map
来执行具有相同运行时属性的等效算法,而不是使用JavaScript对象。
您可以使用Object.entries
、Array#reduce
和Array#map
方法,如下所示:
const input = [ { "id": 1, "price": 22, "from": "00:00:00", "to": "02:00:00" }, { "id": 1, "price": 23, "from": "02:00:00", "to": "04:00:00" }, { "id": 2, "price": 10, "from": "04:00:00", "to": "1.00:00:00" } ],
output = Object.entries(input.reduce(
(acc, {id,...rest}) =>
({...acc, [id]: [...(acc[id] || []), rest]}), {}
))
.map(([id, prices]) => ({id,prices}));
console.log( output );