From: Jeremy Bopp Date: 2010-11-13T01:08:52+09:00 Subject: Re: help sorting objects by their instance field On 11/12/2010 9:43 AM, Aaron Haas wrote: > I'm trying to figure out how to sort objects in an array by one of their > instance > variables, in this case last name. The person class has a first name, > last name, and an address object. The address book class is made up of > an array of persons. How do I sort the array of persons in > alphabetically by the persons last name instance fields. I added a > getLastname method to the persons class, but I'm not sure on the logic. > > [CODE] > class Person > attr_accessor :fname, :lname, :address > > # initializer > def initialize > @fname = @lname = "" > # since address is an object > @address = Address.new > end > > # assign given values to Person object > def crPerson (aFname, aLname, aAddress) > @fname = aFname > @lname = aLname > @address = aAddress > end > > def get_lname > return @lname > end First of all, you don't need the get_lname method. Use Person#lname instead which was created when you called attr_accessor above. It's equivalent. > # string representation of Person > # note the syntax: address.to_s (to call the to_s instance method > of Address class) > def to_s > @fname + " " + @lname + "\n" + "\n" + address.to_s > end > > end > [/CODE] > > [CODE] > class AddressBook > > # class variable. keeps track of number of address book entries > @@instances = 0 FYI, you don't need this. The @persons array knows how many entries it has automatically. Just call @persons.size when you want to know how many entries there are. :-) You should usually avoid class variables in Ruby in my experience in any case. There are times they can make sense, but what would happen here if you had more than a single instance of AddressBook in your program? > # no attr_accessor > # don't want the user to have direct access to @persons > def initialize > @persons = [] # starts with empty array > end > > # add person to address book > def add(person) > @persons += [person] > @@instances += 1 > end > > # delete person from address book > def remove(person) > @persons.delete(person) > @@instances -= 1 > end > # totally lost on this part > # print sorted by last name method using person's get_lname method > def print_addresses > @persons.each { |p| persons[p].get_lname.sort } > end # close while loop > # print sorted array > @persons.each { |p| yield p } > end > > end > [/CODE] You need to call the sort method on the @persons array rather than the string you get from Person#get_lname. There is good documentation for Array#sort and for the closely related sort_by method mixed in from the Enumerable module: http://rdoc.info/docs/ruby-core/1.9.2/Array#sort-instance_method http://rdoc.info/docs/ruby-core/1.9.2/Enumerable#sort_by-instance_method For cases such as learning details of sorting, I have usually found it much better to make a quick script or irb session that pointedly tries to do what I want to do. In this case, I would create a very basic array of strings first and figure out how to sort that. Then I would apply it to your larger program. -Jeremy