Reputation: 93
I have the following array:
[
{:string=>"2:aa/", :count=>2, :char=>"a"},
{:string=>"2:dd/", :count=>2, :char=>"d"},
{:string=>"2:ee/", :count=>2, :char=>"e"},
{:string=>"=:gg/", :count=>2, :char=>"g"},
{:string=>"1:ii/", :count=>2, :char=>"i"},
{:string=>"=:nnn/", :count=>3, :char=>"n"},
{:string=>"1:ooo/", :count=>3, :char=>"o"},
{:string=>"2:sss/", :count=>3, :char=>"s"},
{:string=>"1:uuu/", :count=>3, :char=>"u"}
]
I want this array of hashes to be sorted descending by count, and if count is equal, then I need to sort it ascending based on the char value.
Is there any direct way I can do this?
Upvotes: 0
Views: 665
Reputation: 37507
You asked for a direct way, so here's a way to remove even another indirection--your intermediate data structure. This assumes your hash is just a means to an end and you intend to sort the strings:
strings = ["2:aa/", "2:dd/", "2:ee/", "=:gg/", "1:ii/", "=:nnn/", "1:ooo/", "2:sss/", "1:uuu/"]
strings.sort_by{ |s| x = s[/\w+/]; [-x.size, x] }
The regex isolates the part you need to count and sort; it may need to be adjusted if your real data differs from the example.
(I would replace x
with a more meaningful variable name based on what the letters represent)
Upvotes: 1
Reputation: 114138
Instead of negating the value via -
, you could also use sort
with two arrays and switch the elements as needed.
To sort ascending / ascending you'd use: (see Array#<=>
)
ary.sort { |a, b| [a[:count], a[:char]] <=> [b[:count], b[:char]] }
to sort descending / ascending, you switch the first elements:
ary.sort { |a, b| [b[:count], a[:char]] <=> [a[:count], b[:char]] }
# ^ ^
# | |
# +-------------------------+
to sort ascending / descending, you switch the second elements: (you get the idea)
ary.sort { |a, b| [a[:count], b[:char]] <=> [b[:count], a[:char]] }
# ^ ^
# | |
# +-------------------------+
Upvotes: 6
Reputation: 30056
Try this one
a.sort_by { |item| [-item[:count], item[:char]] }
a
is your array
Upvotes: 5