Search code examples
javascriptsortingobjectmultidimensional-array

Sort nested javascript array / object


I have a Javascript multilevel object like this:

{
    "tennis": {
        "John": {
            "Total_score": 329,
            "Played_games": [
                {
                    "31/12/2024": 151
                },
                {
                    "25/12/2024": 178
                }
            ]
        },
        "Klaas": {
            "Total_score": 188,
            "Played_games": [
                {
                    "10/11/2024": 188
                }
            ]
        }
    },
    "Hockey": {
        "Piet": {
            "Total_score": 166,
            "Played_games": [
                {
                    "01/12/2024": 166
                }
            ]
        }
    },
    "Football": {
        "John": {
            "Total_score": 133,
            "Played_games": [
                {
                    "06/12/2024": 133
                }
            ]
        }
    },
    "Baseball": {
        "Marie": {
            "Total_score": 121,
            "Played_games": [
                {
                    "24/12/2024": 121
                }
            ]
        }
    },
    "Kitesurfing": {
        "Peter": {
            "Total_score": 185,
            "Played_games": [
                {
                    "11/12/2024": 185
                }
            ]
        }
    }
}

How can i sort this array based on total score per game type. So bij example I want to sort on the highest total score for Tennis.

As I'm fairly new to javascript I don't know where to start exactly. Hope you can help me


Solution

  • You would have to flatten the data and then sort the records by score.

    The flattenToRecords function below creates an immutable, flattened copy of the nested structure. This array can now be sorted by any of the fields in each record object.

    const records = flattenToRecords(getRawData())
      .toSorted((a, b) =>
        /* Highest score */
        (b.score - a.score) ||
        /* Most recent */
        (normalizeDate(b.date).localeCompare(normalizeDate(a.date))) ||
        /* Player A-Z */
        (a.player.localeCompare(b.player))
      );
    
    console.log(...records.map(JSON.stringify));
    
    // We neeeed to go deeeeper...
    function flattenToRecords(dict) {
      const results = [];
      for (let sport in dict) {
        const playerDict = dict[sport];
        for (let player in playerDict) {
          const dataDict = playerDict[player];
          const totalScore = dataDict.Total_score;
          for (let game of dataDict.Played_games) {
            for (let date in game) {
              const score = game[date];
              results.push({ date, score, player, sport, totalScore });
            }
          }
        }
      }
      return results;
    }
    
    // Convert 'DD/MM/YYYY' to 'YYYY-MM-DD'
    function normalizeDate(date) {
      return date.split('/').toReversed().join('-');
    }
    
    function getRawData () {
      return {
        "tennis": {
          "John": {
            "Total_score": 329,
            "Played_games": [
              { "31/12/2024": 151 },
              { "25/12/2024": 178 }
            ]
          },
          "Klaas": {
            "Total_score": 188,
            "Played_games": [
              { "10/11/2024": 188 }
            ]
          }
        },
        "Hockey": {
          "Piet": {
            "Total_score": 166,
            "Played_games": [
              { "01/12/2024": 166 }
            ]
          }
        },
        "Football": {
          "John": {
            "Total_score": 133,
            "Played_games": [{
              "06/12/2024": 133
            }]
          }
        },
        "Baseball": {
          "Marie": {
            "Total_score": 121,
            "Played_games": [
              { "24/12/2024": 121 }
            ]
          }
        },
        "Kitesurfing": {
          "Peter": {
            "Total_score": 185,
            "Played_games": [
              { "11/12/2024": 185 }
            ]
          }
        }
      };
    };
    .as-console-row-code { font-size: smaller !important; }
    .as-console-wrapper { top: 0; max-height: 100% !important; }