Reputation: 7105
With a API call i'm receiving a response like below
[
{
stationId: "10"
name: "Jinbaolai"
group: {id: "18", stationGroupName: "Ali"}
},
{
stationId: "13"
name: "Stack"
group: {id: "18", stationGroupName: "Ali"}
},
{
stationId: "20"
name: "Overflow"
group: {id: "19", stationGroupName: "Baba"}
}
]
As you can see first two records consist with the same group. I want to group these data according to the group. So for example it should look like this
[
{
groupId: "18",
groupName : "Ali",
stations : [
{
stationId: "10",
name: "Jinbaolai"
},
{
stationId: "13",
name: "Stack"
}
]
},
{
groupId: "19",
groupName : "Baba",
stations : [
{
stationId: "20",
name: "Overflow"
},
]
}
]
I want to do the grouping logic in my reducer where i also set the full data array that is shown in the beginning of the question.
case EVC_SUCCESS:
return {
...state,
chargingStations: action.evcData.chargingStations,
chargingStationGroups: //This is where my logic should go. ('action.evcData.chargingStations' is the initial data array)
tableLoading: false
}
How can i do this? I tried something using filter
but not successful.
Upvotes: 3
Views: 77
Reputation: 5676
The best way to do this is to use Array.prototype.reduce()
Reduce is an aggregating function where you put in an array of something and get a single vaule back.
There may be a starting value as last parameter like I used {}
.
The signature is reduce(fn, startingValue)
where fn
is a function taking two parameters aggregate
and currentValue
where you return the aggregate in the end.
const groupData = (data)=> {
return Object.values(data.reduce((group,n)=>{
if (!group[n.group.id]){
group[n.group.id] = {
groupId:n.group.id,
groupName: n.group.stationGroupName,
stations:[]}
}
group[n.group.id].stations.push({
stationID: n.stationId,
name: n.name
})
return group;
}, {}))
}
Here is the fiddle
Upvotes: 4
Reputation: 6091
I think chaining multiple functions will work.
const stations = [
{
"stationId": 10,
"name": "Jinbaolai",
"group": {"id": "18", "stationGroupName": "Ali"}
},
{
"stationId": 13,
"name": "Stack",
"group": {"id": 18, "stationGroupName": "Ali"}
},
{
"stationId": 20,
"name": "Overflow",
"group": {"id": "19", "stationGroupName": "Baba"}
}
]
const groups = _.chain(stations)
.groupBy((station) => { return station.group.id })
.map((values, key) => {
return {
"groupId": _.first(values).group.id,
"groupName": _.first(values).group.id,
"stations": _.map(values,(value)=>{ return { "stationId": value.stationId, "name": value.name } })
}
})
console.log("groups",groups)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Upvotes: 0
Reputation: 1005
A simple JS algorithm can do that for you
const list = [
{
stationId: "10",
name: "Jinbaolai",
group: {id: "18", stationGroupName: "Ali"}
},
{
stationId: "13",
name: "Stack",
group: {id: "18", stationGroupName: "Ali"}
},
{
stationId: "20",
name: "Overflow",
group: {id: "19", stationGroupName: "Baba"}
}
];
const groups = {};
list.forEach((item) => {
const groupId = item.group.id;
const group = groups[groupId] || {groupId: groupId, groupName: item.group.stationGroupName, stations: []};
group.stations.push({stationId: item.stationId, name: item.name});
groups[groupId] = group;
});
const groupedArray = Object.keys(groups).map((groupId) => groups[groupId]);
console.log(groupedArray); // This will be the output you want
Upvotes: 1