Ruby - How to sort an array of objects by one field

Sorting an array of objects by one column in the object (class) is pretty simple with Ruby. Here's a quick demo of how I just did this when working on sorting the rows in a CSV file in a simple Ruby script.

Define the class

Step 1 in this is defining my class. So, here's the definition of my Ruby Person class:

class Person <

  # a Person has a first name, last name, and city
  Struct.new(:first_name, :last_name, :city)

  # a method to print out a csv record for the current Person.
  def print_csv_record
    last_name.length==0 ? printf(",") : printf("\"%s\",", last_name)
    first_name.length==0 ? printf(",") : printf("\"%s\",", first_name)
    city.length==0 ? printf("") : printf("\"%s\"", city)
    printf("\n")
  end
end

As you can see, that class has three fields name first_name, last_name, and city. I also included the definition of a method named print_csv_record, which I'll use later in this tutorial.

How to sort the array

Next, assuming I have an array of Person objects, here's how I would sort the array by the last_name column:

# sort the data by the last_name field
people.sort! { |a,b| a.last_name.downcase <=> b.last_name.downcase }

As you can see, that is very simple. It's important to remember to use the ! operator to make sure you sort the people array. If you forget that operator, what you're really doing is returning an array of sorted objects from the people array, but not actually sorting the people array itself.

(By convention, the ! character at the end of a method name indicates that a method will work on the current object, so this is nothing special, I just wanted to make sure I noted it, because I've seen people several times wonder why their array wasn't being sorted.)

How to print the array after it has been sorted

Finally, here's a snippet of Ruby code demonstrating how to sort the array, and then how to print it after it has been sorted.

# sort the data by the last_name field
people.sort! { |a,b| a.last_name.downcase <=> b.last_name.downcase }

# print out all the sorted records (just print to stdout)
people.each { |p|
  p.print_csv_record
}

In this example I also show how to call the print_csv_record method of my Person class, which I defined earlier.

In a future blog post I'll demonstrate how to sort an array of objects using multiple fields in the class, but I'm out of time for today ...