javascript - 在javascript中同时映射和减少数组

标签 javascript arrays mapreduce reduce

我有一个约 1800 个对象的数组,代表联赛中进行的比赛。我需要一个新数组,其中每个团队都有一个对象,并将包含 4 个新字段(winslossesties >点)。这是我正在使用的数组的示例:

[
  {
    "homeGoals": 2,
    "gameId": "12221",
    "homeTeam": {
      "id": "aasfdsf1",
      "teamName": "Team 1"
    },
    "awayTeam": {
      "id": "aasfdsf2",
      "teamName": "Team 2"
    },
    "id": "ggaew1",
    "awayGoals": 4
  },
  {
    "homeGoals": 5,
    "gameId": "12222",
    "homeTeam": {
      "id": "aasfdsf1",
      "teamName": "Team 1"
    },
    "awayTeam": {
      "id": "aasfdsf3",
      "teamName": "Team 3"
    },
    "id": "ggaew2",
    "awayGoals": 1
  },
  {
    "homeGoals": 4,
    "gameId": "12223",
    "homeTeam": {
      "id": "aasfdsf2",
      "teamName": "Team 2"
    },
    "awayTeam": {
      "id": "aasfdsf3",
      "teamName": "Team 3"
    },
    "id": "ggaew3",
    "awayGoals": 4
  },
  {
    "homeGoals": null,
    "gameId": "12223",
    "homeTeam": {
      "id": "aasfdsf2",
      "teamName": "Team 2"
    },
    "awayTeam": {
      "id": "aasfdsf3",
      "teamName": "Team 3"
    },
    "id": "ggaew4",
    "awayGoals": null
  }
]

这是我需要的结果的示例:

 [
  {
    "id": "aasfdsf1",
    "name": "Team 1",
    "wins": 1,
    "losses": 1,
    "ties": 0,
    "points": 2 
  },
  {
    "id": "aasfdsf2",
    "name": "Team 2",
    "wins": 1,
    "losses": 0,
    "ties": 1,
    "points": 3 
  },
  {
    "id": "aasfdsf3",
    "name": "Team 3",
    "wins": 0,
    "losses": 1,
    "ties": 1,
    "points": 1 
  }
]

有些比赛尚未进行,因此 homeGoalsawayGoals 字段将为空。

到目前为止,我有一个独特团队的列表,仅包含比赛已完成的团队:

const completedGames = games.filter(x => x.homeGoals !== null)
const homeTeams = [...new Set(completedGames.map(x => x['homeTeam']))];
const awayTeams = [...new Set(completedGames.map(x => x['awayTeam']))];
const teams = [...new Set([...homeTeams, ...awayTeams])]

我知道我需要执行某种reduce 函数,但我在计算它时遇到了困难。我很确定如果我有适当的 map 缩减功能,我之前所做的步骤将是无关紧要的。任何帮助将不胜感激!

最佳答案

这可以通过 flatMap 以更简单的方式表达。它不是内置在 JS 中,但很容易实现:

let flatMap = (a, fn) => [].concat(...a.map(fn));

现在,在 map 步骤中,您可以为每个游戏发出两个“结果”对象(如果游戏不完整,则根本没有结果):

results = flatMap(data, g => {

    if (g.homeGoals === null || g.awayGoals === null)
        return [];

    if (g.homeGoals > g.awayGoals)
        return [
            {id: g.homeTeam.id, r: 'win'},
            {id: g.awayTeam.id, r: 'loss'},
        ];

    if (g.homeGoals < g.awayGoals)
        return [
            {id: g.homeTeam.id, r: 'loss'},
            {id: g.awayTeam.id, r: 'win'},
        ];

    if (g.homeGoals === g.awayGoals)
        return [
            {id: g.homeTeam.id, r: 'tie'},
            {id: g.awayTeam.id, r: 'tie'},
        ];
});

这会创建一个类似的数组

{ id: 'aasfdsf1', r: 'loss' },
{ id: 'aasfdsf2', r: 'win' },
{ id: 'aasfdsf1', r: 'win' }, etc

很容易减少:

summary = results.reduce((m, {id, r}) => {
    let e = m[id] || {};
    e[r] = (e[r] || 0) + 1;
    return Object.assign(m, {[id]: e})
}, {});

您还可以通过分别将胜利、失败和平局编码为 1、-1、0 来减少冗长,在这种情况下,映射器将变为:

results = flatMap(
    data.filter(g => g.homeGoals !== null),
    g => {
        let d = g.homeGoals - g.awayGoals;
        return [
            {id: g.homeTeam.id, r: Math.sign(+d)},
            {id: g.awayTeam.id, r: Math.sign(-d)},
        ]
    });

关于javascript - 在javascript中同时映射和减少数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46368051/

相关文章:

javascript - 如何根据网站是在本地运行还是在生产环境中为网站中的 JS 变量赋值?

javascript - 使用 ng-repeat 作为嵌入内容的自定义指令

javascript - 尝试定位图标以与两行跨度元素中的第一行文本对齐

c++ - C 将二维数组转换为双指针打印意外值

java - 尝试将 jtable 中的数据显示到控制台时出现 ArrayIndexOutOfBoundsException 错误

hadoop - 如何在映射器输出中收集三个参数。有什么办法

javascript - CouchDB View 使用来自两个单独文档的嵌入式数组组成 JSON 对象

javascript - Jquery 取消移位/取消设置数组项

php - 当php中的数组为空时,json_encode函数不返回大括号{}

asynchronous - F#异步堆栈溢出