Reputation: 825
I have an array of Objects with 4 keys:
[
{
"team": "USA",
"team_profile_id": "10",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "USA",
"team_profile_id": "10",
"player": "The hulk",
"player_id": "10X2"
},
{
"team": "India",
"team_profile_id": "20",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "India",
"team_profile_id": "20",
"player": "SpiderMan",
"player_id": "10X5"
}
]
And I want to group my array by "Teams" such that it creates an array of Player objects for each team
[
{
"team": "USA",
"team_profile_id": "10",
"Players": [
{
"player": "Captain America",
"player_id": "10X1"
},
{
"player": "The hulk",
"player_id": "10X2"
}
]
},
{
"team": "India",
"team_profile_id": "20",
"Players": [
{
"player": "Captain America",
"player_id": "10X1"
},
{
"player": "SpiderMan",
"player_id": "10x5"
}
]
}
]
I am currently trying to use reduce function from MDN prototype but it is not able to handle the sub object creation part.
Currently I have tried:
var group_to_values = result.reduce(function(obj, item) {
obj[item.team] = obj[item.team] || [];
obj[item.team].push({
"team_profile_id":item.team_profile_id,
"player":item.player,
"player_id":item.player_id
});
return obj;
}, {});
But it is not giving the desired result
Upvotes: 0
Views: 874
Reputation: 191976
While you iterate the players with Array.reduce()
, destructure the player object, and separate between the player's properties, and team using spread.
If the team
doesn't exist in the accumulator (r
), create a new object with the team's properties, and the Player: []
property. Push the players into the Players
array of the relevant team. Use Object.values()
to convert back to an array.
const data = [{"team":"USA","team_profile_id":"10","player":"Captain America","player_id":"10X1"},{"team":"USA","team_profile_id":"10","player":"The hulk","player_id":"10X2"},{"team":"India","team_profile_id":"20","player":"Captain America","player_id":"10X1"},{"team":"India","team_profile_id":"20","player":"SpiderMan","player_id":"10X5"}]
const result = Object.values(data.reduce((r, { team, team_profile_id, ...player }) => {
if(!r[team]) r[team] = { team, team_profile_id, Players: [] }
r[team].Players.push(player)
return r
}, {}))
console.log(result)
How to ES5 this solution:
Object.values()
, but we can generate a values()
functions using Object.keys()
.const
s with var
s, arrow functions with functions, destructuring with manual manual assignments.var data = [{"team":"USA","team_profile_id":"10","player":"Captain America","player_id":"10X1"},{"team":"USA","team_profile_id":"10","player":"The hulk","player_id":"10X2"},{"team":"India","team_profile_id":"20","player":"Captain America","player_id":"10X1"},{"team":"India","team_profile_id":"20","player":"SpiderMan","player_id":"10X5"}];
var result = values(data.reduce(function(r, o) {
var team = o.team;
if(!r[team]) r[team] = {
team: team,
team_profile_id: o.team_profile_id,
Players: []
};
r[team].Players.push({ player: o.player, player_id: o.player_id })
return r
}, {}))
function values(obj) {
return Object.keys(obj).map(function(key) {
return obj[key];
});
}
console.log(result)
Upvotes: 1
Reputation: 2355
Try this...
const playerData = [ ... ]
const teamGroups = playerData.reduce ((teamData, playerObj) => {
const targetTeam = teamData.filter(t => t.team === playerObj.team)[0];
if (!targetTeam) {
return [ ...teamData, {
team: playerObj.team,
team_profile_id: playerObj.team_profile_id,
Players: [{
player: playerObj.player,
player_id: playerObj.player_id
}]
}];
}
targetTeam.Players.push ({ player: playerObj.player, player_id: playerObj.player_id });
return teamData;
}, []);
Upvotes: 0
Reputation: 958
Try this:
'use strict';
const inputData = [
{
"team": "USA",
"team_profile_id": "10",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "USA",
"team_profile_id": "10",
"player": "The hulk",
"player_id": "10X2"
},
{
"team": "India",
"team_profile_id": "20",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "India",
"team_profile_id": "20",
"player": "SpiderMan",
"player_id": "10X5"
}
];
function groupByTeams(data) {
// Find the teams
const teams = data.map(({ team }) => team);
const uniqueTeams = [...new Set(teams)];
// Map the array of unique values to return
// desired result.
return uniqueTeams.map(team => {
return {
team,
team_profile_id: data.find((thisTeam) => thisTeam.team === team).team_profile_id,
Players: data
.filter(thisTeam => thisTeam.team === team)
.map(({ player, player_id }) => ({ player_id, player }))
}
});
}
groupByTeams(inputData);
Upvotes: 0
Reputation: 2255
Try the following. First I create a set of unique team names and then filter the data based on that to get a list of relevant players:
const data = [
{
"team": "USA",
"team_profile_id": "10",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "USA",
"team_profile_id": "10",
"player": "The hulk",
"player_id": "10X2"
},
{
"team": "India",
"team_profile_id": "20",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "India",
"team_profile_id": "20",
"player": "SpiderMan",
"player_id": "10X5"
}
];
const res = [...new Set(data.map(e => e.team))]
.map(teamName => ({
team: teamName,
team_profile_id: data.find(e => e.team === teamName).team_profile_id,
Players: data
.filter(p => p.team === teamName)
.map(p => ({
player: p.player,
player_id: p.player_id
}))
}));
console.log(res);
Upvotes: 0
Reputation: 386570
You could find the object and add the new player.
var data = [{ team: "USA", team_profile_id: "10", player: "Captain America", player_id: "10X1" }, { team: "USA", team_profile_id: "10", player: "The hulk", player_id: "10X2" }, { team: "India", team_profile_id: "20", player: "Captain America", player_id: "10X1" }, { team: "India", team_profile_id: "20", player: "SpiderMan", player_id: "10X5" }],
result = data.reduce((r, { team, team_profile_id, player, player_id }) => {
var temp = r.find(q => q.team_profile_id === team_profile_id);
if (!temp) r.push(temp = { team, team_profile_id, Players: [] });
temp.Players.push({ player, player_id });
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 14088
This is probably not the best way to do it but it works.
const players = [
{
"team": "USA",
"team_profile_id": "10",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "USA",
"team_profile_id": "10",
"player": "The hulk",
"player_id": "10X2"
},
{
"team": "India",
"team_profile_id": "20",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "India",
"team_profile_id": "20",
"player": "SpiderMan",
"player_id": "10X5"
}
]
const teams = players.reduce((arr, player) => {
let [team] = arr.filter(t => t.team === player.team)
if (!team) {
team = {
team: player.team,
team_profile_id: player.team_profile_id,
Players: []
}
arr.push(team)
}
team.Players.push({
player: player.player,
player_id: player.player_id
})
return arr
}, [])
console.log(teams)
Upvotes: 0
Reputation: 7665
Since the result needs to be an array you can use it as the initial value for reduce instead of an object:
var players = [
{
"team": "USA",
"team_profile_id": "10",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "USA",
"team_profile_id": "10",
"player": "The hulk",
"player_id": "10X2"
},
{
"team": "India",
"team_profile_id": "20",
"player": "Captain America",
"player_id": "10X1"
},
{
"team": "India",
"team_profile_id": "20",
"player": "SpiderMan",
"player_id": "10X5"
}
]
var teams = players.reduce(function (teams, player) {
var matchingTeams = teams.filter(function(team) {
return team.team === player.team;
});
var team;
if (matchingTeams.length) {
team = matchingTeams[0]
} else {
team = {}
teams.push(team)
}
team.team = player.team;
team.team_profile_id = player.team_profile_id;
var teamPlayer = {
player: player.player,
player_id: player.player_id
};
team.players = team.players ? team.players.concat(teamPlayer) : [teamPlayer];
return teams
}, [])
console.log(teams)
Upvotes: 1