Javascript ES5:如何按键分组并从键值对象的平面数组创建Sub对象,而无需使用Lodash或Undersco



我有一个带有 4 个键的对象数组:

[
{
"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"
}
]

我想按"团队"对我的数组进行分组,以便为每个团队创建一个 Player 对象数组

[
{
"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"
}
]
}
]

我目前正在尝试使用 MDN 原型中的 reduce 函数,但它无法处理子对象创建部分。

目前我已经尝试过:

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;
}, {});

但它没有给出预期的结果

由于结果需要是一个数组,因此您可以将其用作reduce的初始值而不是对象:

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)

您可以找到对象并添加新播放器。

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; }

当您使用Array.reduce()迭代玩家时,解构玩家对象,并使用 spread 在玩家的属性和团队之间分离。

如果累加器(r(中不存在team,则创建一个包含团队属性和Player: []属性的新对象。将玩家推入相关团队的Players阵列中。使用Object.values()转换回数组。

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)

如何ES5此解决方案:

  • 主要问题是Object.values(),但是我们可以使用Object.keys()生成一个values()函数。
  • const替换为vars,将箭头函数替换为函数,将解构替换为手动手动分配。

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)

这可能不是最好的方法,但它有效。

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)

请尝试以下操作。首先,我创建一组唯一的团队名称,然后基于该名称过滤数据以获取相关球员的列表:

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);

试试这个:

'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);

试试这个...

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;
}, []);

相关内容

最新更新