I have searched for an answer on this to no avail, there is a similar question but the answer did not work in this situation, it sorts on a numeric item. Similar Question -That did not work I am trying to use ruby's sort_by to sort one item descending with the other ascending. All I can find is one or the other.
Here is the code:
# Primary sort Last Name Descending, with ties broken by sorting Area of interest.
people = people.sort_by { |a| [ a.last_name, a.area_interest]}
Any guidance would certainly assist.
Sample data:
False means that the list will be sorted in ascending order. True means that the list will be sorted in descending (reverse) order.
This is a straightforward way:
a = [ ['Russell', 'Logic'], ['Euler', 'Graph Theory'],
['Galois', 'Abstract Algebra'], ['Gauss', 'Number Theory'],
['Turing', 'Algorithms'], ['Galois', 'Logic'] ]
a.sort { |(name1,field1),(name2,field2)|
(name1 == name2) ? field1 <=> field2 : name2 <=> name1 }
#=> [ ["Turing", "Algorithms"], ["Russell", "Logic"],
# ["Gauss", "Number Theory"], ["Galois", "Abstract Algebra"],
# ["Galois", "Logic"], ["Euler", "Graph Theory"] ]
For multiple fields, sorting on the first in descending order, then on each of the others, in sequence, in ascending order:
a = [ %w{a b c}, %w{b a d}, %w{a b d}, %w{b c a}, %w{a b c}, %w{b c b}]
#=> [["a", "b", "c"], ["b", "a", "d"], ["a", "b", "d"],
# ["b", "c", "a"], ["a", "b", "c"], ["b", "c", "b"]]
a.sort { |e,f| e.first == f.first ? e[1..-1] <=> f[1..-1] : f <=> e }
#=> [["b", "a", "d"], ["b", "c", "a"], ["b", "c", "b"],
# ["a", "b", "c"], ["a", "b", "c"], ["a", "b", "d"]]
Make a custom class that invert the result of <=>
(including Comparable
).
Wrap the object you want sort descending with the custom class.
Example:
class Descending
include Comparable
attr :obj
def initialize(obj)
@obj = obj
end
def <=>(other)
return -(self.obj <=> other.obj)
end
end
people = [
{last_name: 'Russell', area_interest: 'Logic'},
{last_name: 'Euler', area_interest: 'Graph Theory'},
{last_name: 'Galois', area_interest: 'Abstract Algebra'},
{last_name: 'Gauss', area_interest: 'Number Theory'},
{last_name: 'Turing', area_interest: 'Algorithms'},
{last_name: 'Galois', area_interest: 'Logic'},
]
puts people.sort_by {|person| [
Descending.new(person[:last_name]), # <---------
person[:area_interest],
]}
output:
{:last_name=>"Turing", :area_interest=>"Algorithms"}
{:last_name=>"Russell", :area_interest=>"Logic"}
{:last_name=>"Gauss", :area_interest=>"Number Theory"}
{:last_name=>"Galois", :area_interest=>"Abstract Algebra"}
{:last_name=>"Galois", :area_interest=>"Logic"}
{:last_name=>"Euler", :area_interest=>"Graph Theory"}
BTW, if the object you want sort descending is a numeric value, you can simply use unary operator -
:
people.sort_by {|person| [-person.age, person.name] }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With