# Very easy "sort key" question (but I can't figure it out)

hello,

I have an array, for instance:

a = [ 10, 2, 20, 14, 33]

I want to get:

order= [5, 3, 4, 1, 2]

I’m sure this can be done in one neat line… I only achieve ugly
twisted code to do it… please enlighten me,

many thanks,

Pierre

Hi –

On Wed, 7 May 2008, pierrederome wrote:

I’m sure this can be done in one neat line… I only achieve ugly
twisted code to do it… please enlighten me,

a.sort.reverse would work in this particular case. Otherwise you can
do:

new_array = order.map {|i| a[i-1] }

The reason for the i - 1 thing is that your order goes from 1-5,
whereas the indices of the array are 0-4. But I suspect the
sort.reverse technique might be what you need anyway.

David

Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

pierrederome wrote:

I have an array, for instance:
a = [ 10, 2, 20, 14, 33]
I want to get:
order= [5, 3, 4, 1, 2]

(1…(a.length)).sort {|i, j| a[j-1] <=> a[i-1]}

Though short one-liners are not generally things to aim for. I have
used Perl for almost 20 years and used to get a thrill out of finding
concise ways of doing things, until looking back on them later and
finding it would take me just as long each time to re-work out what was
going on.

Splitting problems up into multiple lines and using intermediate
variables that mean something about the nature or use of the value

Hi –

On Wed, 7 May 2008, David A. Black wrote:

a = [ 10, 2, 20, 14, 33]

new_array = order.map {|i| a[i-1] }

The reason for the i - 1 thing is that your order goes from 1-5,
whereas the indices of the array are 0-4. But I suspect the
sort.reverse technique might be what you need anyway.

So…

To derive the order array from a, you could do:

sorted = a.sort.reverse
order = sorted.map {|e| a.index(e) + 1 }

or (a variant of Mark’s):

order = (1…a.length).sort_by {|i| -a[i-1] }

I’m assuming that you’re always dealing with integers, and that values
are unique.

David

Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

thanks a lot !

in the end I did something pretty close

b= []
a.each_with_index { |v,i| b[i] = [ v, i ] }
order=b.sort_by { |o| o[0] }.map { |v| v[1] }.reverse

cause values were not unique indeed…

On May 7, 2008, at 5:29 AM, pierrederome wrote:

I’m sure this can be done in one neat line… I only achieve ugly
twisted code to do it… please enlighten me,

many thanks,

Pierre

On May 7, 2008, at 7:01 AM, pierrederome wrote:

thanks a lot !

in the end I did something pretty close

b= []
a.each_with_index { |v,i| b[i] = [ v, i ] }
order=b.sort_by { |o| o[0] }.map { |v| v[1] }.reverse

cause values were not unique indeed…

Pierre,
You may have solved your problem, but I’d be surprised if anyone else
could possibly grasp what that problem really was. David said, “Based
on Mark’s answer, I think I misunderstood your question.” I think it
more accurate to say, “Based on your vague question, I’m not sure what

that would have been MUCH more clear:

Given an array of integers (which are not necessarily
unique), I need to construct the array that gives the
1-based (rather than the natural 0-based) “place values”
of those integers, but counting from the end of the
original array.
For example,
a = [ 10, 2, 20, 14, 33]
should produce the array:
[ 5, 3, 4, 1, 2 ]
because the last value, 33, would come in “5th place”,
then 14 would come in “3rd place”, etc.

Then perhaps a bit of context as to WHY such a transformation is
useful to you. It’s entirely possibly that knowing more about your
problem would give you a solution that you might have never imagined.