Multi string-element sort on Ruby hash, first key descending, second key ascending

1k views Asked by At

Given the following array of hashes:

values = [
  {"one"=>"BA", "two"=>"AAB"},
  {"one"=>"AA", "two"=>"BBA"},
  {"one"=>"AA", "two"=>"BCB"},
  {"one"=>"AA", "two"=>"ABA"},
  {"one"=>"BC", "two"=>"AAC"},
  {"one"=>"AC", "two"=>"AAB"},
  {"one"=>"AC", "two"=>"AAA"},
  {"one"=>"AB", "two"=>"BCC"}
]

How do I get the following output:

  {"one"=>"BC", "two"=>"AAC"}
  {"one"=>"BA", "two"=>"AAB"}
  {"one"=>"AC", "two"=>"AAA"}
  {"one"=>"AC", "two"=>"AAB"}
  {"one"=>"AB", "two"=>"BCC"}
  {"one"=>"AA", "two"=>"ABA"}
  {"one"=>"AA", "two"=>"BBA"}
  {"one"=>"AA", "two"=>"BCB"}

I can do this easily enough if both key values point to integers:

multi_sort = values.sort_by { |x| [-x["one"], x["two"] ] }

What is the syntax to do this with string values?

1

There are 1 answers

1
tadman On BEST ANSWER

You might need to write a full sort method:

values.sort { |a,b| a["one"] == b["one"] ? a["two"] <=> b["two"] : b["one"] <=> a["one"] }

Note that the order of the comparison is b vs a for "one" and a vs b for "two".

This could be a lot more concise if you'd used symbol keys instead of strings.