I recently came across the problem of having to sort an array, where the
members are objects of a Struct type, and I need to define a custom
comparision function on certain elements of this type. To illustrate the
problem, think of having
Customer = Struct.new(:custno, :first_name, :family_name, :title,
:addr1, :addr2, :country, :and, :many, :more)
and that I have an array ‘customers’ of elements of type Customer, and I
would like to produce a sorted version of the array, sorted first by
:family_name, then by :title, then by :custno, and finally by
:first_name. To start with:
sorted_customers = customers.sort_by {|left,right|
cust_comp(left,right)}
The question is: How can we define cust_comp, so that it looks nice,
understandable and maintainable?
Here is one approach (which I don’t really like):
SORT_FIELDS=%s(family_name, title, custno, first_name)
def cust_comp(a,b)
result=0
SORT_FIELDS.detect do |field|
result = a.send(:field) <=> b.send(:field)
result != 0
end
result
end
It is ugly, because of the need of the “outside” variable ‘result’ to
keep track of the result so far.
Any idea how to write this in a nicer way?