按ID修改和组合对象阵列



我有以下对象数组:

[
{
"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时,我们会创建一个新对象,其中包含idprices数组以及当前值(没有id属性)。如果我们已经遇到了相同的id,我们只需要将当前值(不带id属性)推送到已经存在的数组。

由于我们只有一个循环,查找需要O(1)时间,因此该算法需要O(n)才能给出有效结果。

使用这个一行

const objWithoutId = (({id, ...o}) => o)(cur);

我们创建了一个新的对象,它包含除CCD_ 13之外的所有属性。

Lat,但同样重要的是,我们只需要使用Object.values()获取创建的JavaScript对象的值。您也可以使用Map来执行具有相同运行时属性的等效算法,而不是使用JavaScript对象。

您可以使用Object.entriesArray#reduceArray#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 );

最新更新