RSS Log in
 

Notes on sorting collections in Ruby.

 

sort method

numbers = [1 , 3, 5, 2, 4]
p numbers.sort

 

Defining <=>

The spaceship operator (<=>) was covered in Literal constructors, built-in operators and conversion methods but it can also be used to define the sorting criteria.

 

class Person
    attr_accessor :name, :age, :country
 
    def initialize(name, age, country)
        self.name = name
        self.age = age
        self.country = country
    end
 
    def <=>(other_person)
        self.age <=> other_person.age
    end
 
    def to_s
        self.name
    end
end
 
p1 = Person.new("Bill", 20, "UK")
p2 = Person.new("Bob", 30, "France")
p3 = Person.new("Ben", 50, "France")
 
people = [p2, p3, p1]

p people
p people.sort

Output:

[Bob, Ben, Bill]
[Bill, Bob, Ben]

 

Mixing Comparable

Other type of comparison (<, >, ==, etc.) can be performed by mixing the Comparable module:

class Person
    include Comparable
 
    attr_accessor :name, :age, :country
 
    def initialize(name, age, country)
        self.name = name
        self.age = age
        self.country = country
    end
 
    def <=>(other_person)
        self.age <=> other_person.age
    end

    def to_s
        "#{self.name}:#{self.age}"
    end
end
 
p1 = Person.new("Bill", 20, "UK")
p2 = Person.new("Bob", 30, "France")
p3 = Person.new("Ben", 50, "France")
 
people = [p2, p3, p1]

p people.sort

puts p1.eql?(p2)
puts p1.equal?(p2)
 
puts p1 == p2
puts p1 < p2
puts p1 >= p2

 

Code block as sorting criteria

class Person
    attr_accessor :name, :age, :country
 
    def initialize(name, age, country)
        self.name = name
        self.age = age
        self.country = country
    end
 
    def <=>(other_person)
        self.age <=> other_person.age
    end

    def to_s
        "#{self.name}:#{self.age}"
    end
end
 
p1 = Person.new("Bill", 20, "UK")
p2 = Person.new("Bob", 30, "France")
p3 = Person.new("Ben", 50, "France")
 
people = [p2, p3, p1]

p people
p people.sort

# Equivalent: 
# people.sort {|first, second| first.name <=> second.name}
sorted = people.sort do |first, second|
    first.name <=> second.name    
end

p sorted

Output:

[Bob:30, Ben:50, Bill:20]
[Bill:20, Bob:30, Ben:50]
[Ben:50, Bill:20, Bob:30]

 

sort_by

The sorb_by method is similar to calling the sort method with a code block but more ‘sugary’:

class Person
    attr_accessor :name, :age, :country
 
    def initialize(name, age, country)
        self.name = name
        self.age = age
        self.country = country
    end
 
    def <=>(other_person)
        self.age <=> other_person.age
    end

    def to_s
        "#{self.name}:#{self.age}"
    end
end
 
p1 = Person.new("Bill", 20, "UK")
p2 = Person.new("Bob", 30, "France")
p3 = Person.new("Ben", 50, "France")
 
people = [p2, p3, p1]
p people.sort_by {|person| person.name}

Comments are closed
© Copyright 2012 TheBooleanFrog Powered by: BlogEngine.NET|Credits|Subscribe via RSS

Follow

twitter linkedin linkedin rss

TheBooleanFrog

Programming sticky notes and other distractions...