Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting an array of structs

I have an array of structs called leaders. The struct class looks like this, for contextual info:

class Leader < Struct.new(:rank, :user); end

Two questions:

  1. How do I sort the array of structs by rank?
  2. How do I sort the array of structs by rank and by user.created_at?
like image 509
keruilin Avatar asked Oct 20 '25 00:10

keruilin


2 Answers

1.

Assuming rank is numeric:

array.sort {| a, b | a[:rank] <=> b[:rank] }

This is just specifying that we compare a and b using [:rank].

2. 

array.sort {| a, b | a[:rank] == b[:rank] ? 
    a[:user].created_at <=> b[:user].created_at : 
    a[:rank] <=> b[:rank] }

This uses a ternary. If the ranks are equal, we compare by [:user].created_at. Otherwise, we compare by the ranks.

You could implement <=> in your own class to allow sorting natively:

class Leader < Struct.new(:rank, :user)
  def <=>(other)
    self[:rank] <=> other[:rank]
  end
end

Then you can do:

leaders.sort()

If you include Comparable, it will provide the other comparison operators too.

like image 111
Matthew Flaschen Avatar answered Oct 21 '25 16:10

Matthew Flaschen


Here's an implementation using sort_by. As noted in the documentation, it may be less efficient than a version using sort, depending on how expensive it is to retrieve the rank and created_at values.

Sorting by rank:

leaders.sort_by {|l| l.rank}

Sorting by rank and created_at:

leaders.sort_by {|l| [l.rank, l.user.created_at]}
like image 33
Greg Campbell Avatar answered Oct 21 '25 14:10

Greg Campbell