【问题标题】:map and reduce an array at the same time in javascript在javascript中同时映射和减少一个数组
【发布时间】:2017-09-22 15:18:13
【问题描述】:

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

[
  {
    "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 reduce 功能,我很确定我之前所做的步骤将是无关紧要的。任何帮助将不胜感激!

【问题讨论】:

    标签: javascript arrays mapreduce reduce


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 感谢您的帮助!
    • summary 函数返回一个对象的对象,我如何让它成为一个数组?我尝试将函数末尾的{} 更改为[],但返回的是一个空白数组。
    【解决方案2】:

    我认为您正在寻找这样的东西:

    const hashMapTeams = games.filter(x => x.homeGoals !== null)
    .reduce((res, match)=>{
       /* do the calculations here */
       /* put the values on the res object, using res as a HashMap*/
        res["/*the home team id*/"].id = /*id value*/
        res["/*the home team id*/"].name = /*name value*/
        res["/*the home team id*/"].wins= /* the right value */;
        res["/*the home team id*/"].losses= /* the right value */;
        res["/*the home team id*/"].ties= /* the right value */;
        res["/*the home team id*/"].points= /* the right value */;
    
        res["/*the away team id*/"].id = /*id value*/
        res["/*the away team id*/"].name = /*name value*/
        res["/*the away team id*/"].wins= /* the right value */;
        res["/*the away team id*/"].losses= /* the right value */;
        res["/*the away team id*/"].ties= /* the right value */;
        res["/*the away team id*/"].points= /* the right value */;
     },{});
    
    /* This will convert again the object to an array */
    const arrayTeams = Object.keys(hashMapTeams).map(function (key) { return hashMapTeams[key]; });
    

    【讨论】:

      【解决方案3】:

      这将得到您正在寻找的确切结果:

      {
        "id": "aasfdsf1",
        "name": "Team 1",
        "wins": 1,
        "losses": 1,
        "ties": 0,
        "points": 2 
      },
      

      我使用三元组和方括号向您展示了不止一种方法,您可以使用任何一种。

      let result = [];
      
      your1800ArrayObj.map(data => {      
          let wins = data.wins ? data.wins : 0;
          let losses = data.losses ? data.losses : 0;
          let ties = data['ties'] || 0;
          let points = data['points'] || 0;
      
          if (data.homeGoals === null && data.awayGoals === null) {
              console.log('game not played')
              } else {
                  if (data.homeGoals > data.awayGoals) {
                      wins += 1
                      points += 1
                  } else if (data.homeGoals < data.awayGoals) {
                      losses += 1
                  } else {
                      ties += 1
                  }
              }
      
          result.push({
              id: data.id,
              name: data.homeTeam.teamName ,
              wins: wins,
              losses: losses,
              ties: ties,
              points: points
          })
      })
      
      return result
      }
      

      【讨论】:

        猜你喜欢
        • 2018-01-28
        • 1970-01-01
        • 2012-03-09
        • 1970-01-01
        • 1970-01-01
        • 2016-05-05
        • 2016-03-04
        • 2023-04-03
        • 1970-01-01
        相关资源
        最近更新 更多