On Oct 14, 8:00am, Steve H. [email protected] wrote:
Another thread here, suggested using a minus for Numbers but what about
def compare(a,b, key_methods)
a, b = b, a
end.sort do |a, b|
[“radio”, 20, 5],
[“archie”, 20, 5],
[“newton”, 10, 3]
]
puts a.sort_by(
[Proc.new { |a| a[0] }],
[Proc.new { |a| a[1] }, :desc]
).inspect
Oops, I forgot to verify that I was actually caching results. Here is
a fixed version.
module Enumerable
def sort_by_multi(*key_methods)
# allow for multiple key_methods and only
# evaluate them when they are truly needed
# for the sort
def compare(a,b, key_methods)
i = 0
while i < key_methods.size do
for elem in [a, b] do
key = elem[1]
if elem[0].size <= i
elem[0] << key_methods[i][0].call(key)
puts " #{elem.inspect}"
end
end
if key_methods[i][1] == :desc
a, b = b, a
end
result = (a[0][i] <=> b[0][i])
return result unless result == 0
i += 1
end
return result
end
self.collect do |item|
[ [], item ]
end.sort do |a, b|
compare(a, b, key_methods)
end.collect do |kv|
kv[1]
end
end
end
a = [
[“radio”, 30, 5],
[“radio”, 40, 5],
[“radio”, 20, 5],
[“archie”, 20, 5],
[“newton”, 10, 3]
]
puts a.sort_by_multi(
[Proc.new { |a| a[0] }],
[Proc.new { |a| a[1] }, :desc]
).inspect
You can see that it only evaluates the second key for tiebreaker
purposes. (Of course, in this example, the key calculation is
trivial, but in the real world you might have a key that is expensive
to evaluate.)
[[“radio”], [“radio”, 30, 5]]
[[“radio”], [“radio”, 20, 5]]
[[“radio”, 30], [“radio”, 30, 5]]
[[“radio”, 20], [“radio”, 20, 5]]
[[“newton”], [“newton”, 10, 3]]
[[“radio”], [“radio”, 40, 5]]
[[“radio”, 40], [“radio”, 40, 5]]
[[“archie”], [“archie”, 20, 5]]
[[“archie”, 20, 5], [“newton”, 10, 3], [“radio”, 40, 5], [“radio”, 30,
5], [“radio”, 20, 5]]