前端数据转换求助:按日期聚合多渠道消费数据的实现方案
The issue with your current map approach is that it creates a new object for every single element in the array—so you end up with duplicate date entries instead of grouping channels under the same date. To fix this, we need to group the data by date first, then structure each group into the format you want.
Efficient Approach Using Map (Best for Large Datasets)
Using a Map allows us to quickly look up existing date entries in constant time, making this solution efficient even with lots of data:
// Assume your original array is called 'arr' const arr = [ { "channel_number": 1, "id_channel": "св-1312", "consumption": 1231, "date": 1 }, { "channel_number": 1, "id_channel": "св-1312", "consumption": 1234, "date": 2 }, { "channel_number": 1, "id_channel": "св-1312", "consumption": 1234, "date": 3 }, { "channel_number": 2, "id_channel": "св-1314", "consumption": 800, "date": 1 }, { "channel_number": 2, "id_channel": "св-1314", "consumption": 823, "date": 2 }, { "channel_number": 2, "id_channel": "св-1314", "consumption": 1233, "date": 3 } ]; // Step 1: Create a Map to group entries by date const dateGroups = new Map<number, { date: number; channels: { channel_number: number; consumption: number }[] }>(); // Step 2: Iterate over each item and populate the Map arr.forEach(item => { const { date, channel_number, consumption } = item; // Check if the date already exists in our Map if (dateGroups.has(date)) { // If it does, add the channel data to the existing channels array dateGroups.get(date)!.channels.push({ channel_number, consumption }); } else { // If not, create a new entry for this date dateGroups.set(date, { date, channels: [{ channel_number, consumption }] }); } }); // Step 3: Convert the Map values into the final array const result = Array.from(dateGroups.values()); console.log(result);
How This Works:
- The
Mapuses thedateas its key, so each date is unique in the map. - For each item in your original array:
- If the date is already in the map, we append the channel's consumption data to its
channelsarray. - If the date is new, we create a new entry with the date and an initial
channelsarray containing the current item's data.
- If the date is already in the map, we append the channel's consumption data to its
- Finally,
Array.from(dateGroups.values())converts the map's values into the array structure you need.
Alternative: Using reduce (Simpler for Small Datasets)
If your dataset is small, you can use Array.reduce to achieve the same result in a more concise way (note: this is less efficient for large data because find runs in O(n) time per iteration):
const result = arr.reduce((acc, item) => { const { date, channel_number, consumption } = item; // Find existing entry for this date const existingDateEntry = acc.find(entry => entry.date === date); if (existingDateEntry) { existingDateEntry.channels.push({ channel_number, consumption }); } else { acc.push({ date, channels: [{ channel_number, consumption }] }); } return acc; }, [] as { date: number; channels: { channel_number: number; consumption: number }[] }[]);
Sample Output
Both approaches will produce the desired structure for your sample data:
[ { date: 1, channels: [ { channel_number: 1, consumption: 1231 }, { channel_number: 2, consumption: 800 } ] }, { date: 2, channels: [ { channel_number: 1, consumption: 1234 }, { channel_number: 2, consumption: 823 } ] }, { date: 3, channels: [ { channel_number: 1, consumption: 1234 }, { channel_number: 2, consumption: 1233 } ] } ]
内容的提问来源于stack exchange,提问作者Gi S

