KellyCMI
KellyCMI

Reputation: 197

Javascript: sorting objects in objects

As you may assume - I'm stuck ;) My problem is that I have an object with some other objects within:

let players = {
  buggy: {
    name: 'John',
    surname: 'Cocroach',
    rank: 872
  },
  valentino: {
    name: 'Antonio',
    surname: 'Valencia',
    rank: 788
  },
  tommy: {
    name: 'Tom',
    surname: 'Witcher',
    rank: 101
  },
};

And what I want to do is to sort "players" object by "rank": (tommy(101), valentino(788), buggy(872)) or by a string (e.g. "surname"). What is more I want it to still be an object (I am using it in several other functions ;) )

I tried some ideas form here (e.g. converting to an array), but all were uneffective. What would be the best option?

Upvotes: 1

Views: 64

Answers (2)

Ele
Ele

Reputation: 33726

You can sort the keys and then return an iterable object. This way you will be able to loop it.

Another approach is using a simple array with the keys, Etc, however this approach (iterable object) is cleaner.

Let's create a function called sortAsIterable(..), this function will return an iterable object of players.

Important: Be careful with IE

let players = {  buggy: {    name: 'John',    surname: 'Cocroach',    rank: 872  },  valentino: {    name: 'Antonio',    surname: 'Valencia',    rank: 788  },  tommy: {    name: 'Tom',    surname: 'Witcher',    rank: 101  },};

function sortAsIterable(obj) {
  let sortedKeys = Object.keys(obj).sort(function(a, b) {
    return obj[a].rank - obj[b].rank;
  });
  
  let myIterable = {}, index = 0;
  myIterable[Symbol.iterator] = function*() {
    for (let k of sortedKeys) yield {[k]: obj[k]};
  };
  
  return myIterable;
}

// Object sorted.
let sortedPlayers = sortAsIterable(players); 
players.buggy.name = "Ele"; // This is to illustrate the live access to the values.

// Now you can iterate them .
// You can do this as much as you want, for example in different parts of your code.
for (let player of sortedPlayers) console.log(player);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Resources

Upvotes: 1

Jonas Wilms
Jonas Wilms

Reputation: 138527

As objects are stored by reference you can have an array and an object operating on the same underlying player objects:

 const playersByRank = Object.values(players).sort((a, b) => a.rank - b.rank);

Now you can access a player either via its name under players or via its relative rank under playersByRank, e.g. taking the player "buggy" is the same as taking the highest ranked player:

players.buggy.test = "works";
console.log(playersByRank[0].test);

Upvotes: 1

Related Questions