Let’s say I have an array, each element of which is a 2-dimensional array
of ints.
I want to sort with the first element in the 2D array taking precedence,
but using the second as a tiebreaker.
So far, I haven’t come up with a nice idiom that doesn’t seem a bit kludgy:
What I tried was to do something like:
x.sort {|a,b| a[0]<=>b[0] || a[1]<=>b[1]}
but 0 is not false in Ruby so this doesn’t work.
x.sort {|a,b| 2*(a[0]<=>b[0]) + (a[1]<=>b[1])}
works, but is non-intuitive and not pretty.
Does anyone have a nice clean rubyesque idiom for this?
Let’s say I have an array, each element of which is a 2-dimensional array
of ints.
I want to sort with the first element in the 2D array taking precedence,
but using the second as a tiebreaker.
So far, I haven’t come up with a nice idiom that doesn’t seem a bit kludgy:
What I tried was to do something like:
x.sort {|a,b| a[0]<=>b[0] || a[1]<=>b[1]}
but 0 is not false in Ruby so this doesn’t work.
x.sort {|a,b| 2*(a[0]<=>b[0]) + (a[1]<=>b[1])}
works, but is non-intuitive and not pretty.
Does anyone have a nice clean rubyesque idiom for this?
Rubyesque idiom? Probably not, but this is readable:
y = x.sort{|a,b|
if (result = a[0]<=>b[0]) != 0
result
else
a[1]<=>b[1]
end
}
···
On Tuesday 10 September 2002 01:35 pm, Brett Williams wrote:
Let’s say I have an array, each element of which is a 2-dimensional array
of ints.
I want to sort with the first element in the 2D array taking precedence,
but using the second as a tiebreaker.
So far, I haven’t come up with a nice idiom that doesn’t seem a bit kludgy:
What I tried was to do something like:
x.sort {|a,b| a[0]<=>b[0] || a[1]<=>b[1]}
but 0 is not false in Ruby so this doesn’t work.
x.sort {|a,b| 2*(a[0]<=>b[0]) + (a[1]<=>b[1])}
works, but is non-intuitive and not pretty.
Does anyone have a nice clean rubyesque idiom for this?
Let’s say I have an array, each element of which is a 2-dimensional array
of ints.
I want to sort with the first element in the 2D array taking precedence,
but using the second as a tiebreaker.
[snip]
You can use Numeric’s nonzero? e.g.
I was wrong. Interesting behaviour - nice but confusing - I would have
thought that what with operators being mostly implemented as methods,
the result of nonzero? would be returned instead of the result of
a[0]<=>b[0]. Is there a definitive statement of which operators/methods
modify the “last expression executed”?
I was wrong. Interesting behaviour - nice but confusing - I would have
thought that what with operators being mostly implemented as methods,
the result of nonzero? would be returned instead of the result of
a[0]<=>b[0]. Is there a definitive statement of which operators/methods
modify the “last expression executed”?
Historically, nonzero? was introduced for very this kind of sort (what
is the correct name?). But Array#<=> was introduced in no time after
nonzero? was. Tadayoshi Funaba, who is the inventor of nonzero? and
Array#<=>, said that that Array#<=> might obsolets nonzero?. He
thought that a user however could choose favorite one [ruby-list:8546].
I prefer Array#<=> way.
In 1.7.x, we can do
x.sort_by{|a| [a[1],a[2],a[0]]}
instead of
x.sort{|a,b| [a[1],a[2],a[0]] <=> [b[1],b[2],b[0]]}
and the former is faster than the latter because sort_by implements
Schwartzian transform(*1) in C.
sort_by in Ruby is defined in shim(*2) for 1.6.x as follows:
module Enumerable
def sort_by
ary = map { |i| [yield(i), i] }
ary.sort! { |a, b| a[0] <=> b[0] }
ary.map! { |i| i[1] }
end
end