1

I have an array of ~1800 object represents games played in a league. I need a new array that has an object for each team, and will include 4 new fields (wins, losses, ties, and points). Here is a sample of the array I am working with:

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

And here is an example of what I need the result to look like:

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

Some games have not been played, so the homeGoals and awayGoals fields will be null.

So far I have a list of unique teams, only where the games have been completed:

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

I know I need to do some sort of reduce function, but am having trouble figuring it. I am pretty sure the step I just did before would be irrelevant if I had a proper map reduce function. Any help would be greatly appreciated !

0

3 Answers 3

3

This can be expressed in a simpler way with flatMap. It's not built-in in JS, but easy to implement:

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

Now, on the map step, you can emit two "result" object per game (or no results at all if the game is incomplete):

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

This creates an array like

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

which is easy to reduce:

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

You can also make is less verbose by encoding wins, losses and ties by 1, -1, 0 respectively, in which case the mapper becomes:

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)},
        ]
    });
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the help !
The summary function is returning an object of objects, how do i get that to be an array? I tried changing the {} at the end of the function to [], but that returned a blank array.
1

I think you are looking to something like this:

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

Comments

0

This gets the exactly result you are looking for:

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

I used tenary and brackets to show you more than one way to approach that, you can use either one.

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
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.