A sort_by descending sort

  • Thread starter Michael Gaunnac
  • Start date
M

Michael Gaunnac

------=_NextPart_000_00D6_01C4AD13.37086F20
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Perhaps this has already been covered, but I discovered this idiom for =
doing a descending sort using sort_by.

arr =3D Array.new
(0..20).each {|i| arr.push sprintf('%02d', i)}
p arr
#=3D>["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", =
"11", "12", "13", "14", "15", "16", "17", "18", "19", "20"]

arr =3D arr.sort_by {|i| [i.slice(0,2).tr('0-9','9876543210')]} # =
descending sort using 9's complement

p arr
#=3D>["20", "19", "18", "17", "16", "15", "14", "13", "12", "11", "10", =
"09", "08", "07", "06", "05", "04", "03", "02", "01", "00"]

Mike
------=_NextPart_000_00D6_01C4AD13.37086F20--
 
G

Gavin Kistner

arr = arr.sort_by {|i| [i.slice(0,2).tr('0-9','9876543210')]} #
descending sort using 9's complement

Tricky, but how about just:

arr = arr.sort_by{ |n| -n.to_i }

?
 
M

Michael Gaunnac

Gavin said:
arr = arr.sort_by {|i| [i.slice(0,2).tr('0-9','9876543210')]} #
descending sort using 9's complement

Tricky, but how about just:

arr = arr.sort_by{ |n| -n.to_i }

?
Well, I was working with longer strings that I had to slice several keys
from. I guess I simplified the context too much.

Mike
 
B

Brian Candler

Perhaps this has already been covered, but I discovered this idiom for doing a descending sort using sort_by.

arr = Array.new
(0..20).each {|i| arr.push sprintf('%02d', i)}
p arr
#=>["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"]

arr = arr.sort_by {|i| [i.slice(0,2).tr('0-9','9876543210')]} # descending sort using 9's complement

p arr
#=>["20", "19", "18", "17", "16", "15", "14", "13", "12", "11", "10", "09", "08", "07", "06", "05", "04", "03", "02", "01", "00"]

arr2 = arr1.sort.reverse!
or
arr2 = arr1.sort_by { |i| ... }.reverse!

I'd guess that would be quicker and less memory-hungry than generating
temporary string objects with translated characters in them.

Regards,

Brian.
 
M

Michael Gaunnac

gabriele said:
Michael Gaunnac ha scritto:
Perhaps this has already been covered, but I discovered this idiom
for doing a descending sort using sort_by.

why not:
[1,2.0,6,23 ,546,421.1,,0.1].sort_by {|x| 1-x}
=> [546, 421.1, 23, 6, 2.0, 1, 0.1]

Anyway, thankx for making me think of this :)

More context:

arr = %W{
A10/04/200420:30
A10/04/200405:00
A10/04/200420:00
A10/06/200405:00
A10/07/200409:37
A10/07/200419:00
A10/07/200421:30
E10/08/200404:00
A10/08/200407:50
A10/08/200405:15
D10/08/200404:00
A10/08/200305:00
A10/08/200405:00
A10/08/200403:55
B10/08/200404:15
A10/07/200419:30
A10/07/200422:00
B10/07/200405:00
B10/08/200407:50
A10/08/200407:50
A10/08/200407:25
C10/08/200404:00
B10/08/200404:00
A10/08/200404:45
A10/08/200404:10
B10/08/200404:10
A10/08/200404:00
}
# sort ascending descending year
descending month/day descending hour:minute
arr = arr.sort_by {|i| [[i.slice(0,1)],
[i.slice(7,4).tr('0-9','9876543210')],
[i.slice(1,5).tr('/0-9','/9876543210')],
[i.slice(11,5).tr(':0-9',':9876543210')]]}

arr.each {|i| print i, "\n"}


<challenge>
Can this sort be simplified (with Ruby of course)?
</challenge>
 
G

gabriele renzi

Michael Gaunnac ha scritto:
gabriele said:
Michael Gaunnac ha scritto:

Perhaps this has already been covered, but I discovered this idiom
for doing a descending sort using sort_by.

why not:
[1,2.0,6,23 ,546,421.1,,0.1].sort_by {|x| 1-x}
=> [546, 421.1, 23, 6, 2.0, 1, 0.1]

Anyway, thankx for making me think of this :)


More context:

arr = %W{
A10/04/200420:30
A10/04/200405:00
A10/04/200420:00
A10/06/200405:00
A10/07/200409:37
A10/07/200419:00
A10/07/200421:30
E10/08/200404:00
A10/08/200407:50
A10/08/200405:15
D10/08/200404:00
A10/08/200305:00
A10/08/200405:00
A10/08/200403:55
B10/08/200404:15
A10/07/200419:30
A10/07/200422:00
B10/07/200405:00
B10/08/200407:50
A10/08/200407:50
A10/08/200407:25
C10/08/200404:00
B10/08/200404:00
A10/08/200404:45
A10/08/200404:10
B10/08/200404:10
A10/08/200404:00
}
# sort ascending descending year
descending month/day descending hour:minute
arr = arr.sort_by {|i| [[i.slice(0,1)],
[i.slice(7,4).tr('0-9','9876543210')],
[i.slice(1,5).tr('/0-9','/9876543210')],
[i.slice(11,5).tr(':0-9',':9876543210')]]}

arr.each {|i| print i, "\n"}


<challenge>
Can this sort be simplified (with Ruby of course)?
</challenge>


ah, I see :)
well, you can remove 6 []

arr = arr.sort_by {|i| [i.slice(0,1),
i.slice(7,4).tr('0-9','9876543210'),
i.slice(1,5).tr('/0-9','/9876543210'),
i.slice(11,5).tr(':0-9',':9876543210')]}

then readd them in defferent places:

arr = arr.sort_by {|i| [i[0,1],
i[7,4].tr('0-9','9876543210'),
i[1,5].tr('/0-9','/9876543210'),
i[11,5].tr(':0-9',':9876543210')]}

but I guess I'd just use sort +reverse, and I'm not good at golf :/
 
M

Mark Hubbart

gabriele said:
Michael Gaunnac ha scritto:
Perhaps this has already been covered, but I discovered this idiom
for doing a descending sort using sort_by.

why not:
[1,2.0,6,23 ,546,421.1,,0.1].sort_by {|x| 1-x}
=> [546, 421.1, 23, 6, 2.0, 1, 0.1]

Anyway, thankx for making me think of this :)

More context:

arr = %W{
A10/04/200420:30
A10/04/200405:00
A10/04/200420:00
A10/06/200405:00
A10/07/200409:37
A10/07/200419:00
A10/07/200421:30
E10/08/200404:00
A10/08/200407:50
A10/08/200405:15
D10/08/200404:00
A10/08/200305:00
A10/08/200405:00
A10/08/200403:55
B10/08/200404:15
A10/07/200419:30
A10/07/200422:00
B10/07/200405:00
B10/08/200407:50
A10/08/200407:50
A10/08/200407:25
C10/08/200404:00
B10/08/200404:00
A10/08/200404:45
A10/08/200404:10
B10/08/200404:10
A10/08/200404:00
}
# sort ascending descending year
descending month/day descending hour:minute
arr = arr.sort_by {|i| [[i.slice(0,1)],
[i.slice(7,4).tr('0-9','9876543210')],
[i.slice(1,5).tr('/0-9','/9876543210')],
[i.slice(11,5).tr(':0-9',':9876543210')]]}

arr.each {|i| print i, "\n"}

<challenge>
Can this sort be simplified (with Ruby of course)?
</challenge>

assuming an unchanging format, perhaps:

arr = arr.sort_by do |i|
i.scan(/(.)(..).(..).(....)(..):(..)/).map do |a,*date|
m,d,y,h,n = *date.map{|x| x.to_i}
[a,-y,-m,-d,-h,-n]
end
end

cheers,
Mark
 
B

Brian Candler

# sort ascending descending year
descending month/day descending hour:minute
arr = arr.sort_by {|i| [[i.slice(0,1)],
[i.slice(7,4).tr('0-9','9876543210')],
[i.slice(1,5).tr('/0-9','/9876543210')],
[i.slice(11,5).tr(':0-9',':9876543210')]]}

arr.each {|i| print i, "\n"}


<challenge>
Can this sort be simplified (with Ruby of course)?
</challenge>

Arguably cheating, and very specific to this particular example, but:

arr2 = arr.sort_by { |i|
[-i[0], i[7..10], i[4..5], i[1..2], i[11..15]]
}.reverse!

For a more general pattern, how about:

module Rev
def <=>(other); -super; end
end

arr3 = arr.sort_by { |i|
[i[0..0], i[7..10].extend(Rev), i[4..5].extend(Rev),
i[1..2].extend(Rev), i[11..15].extend(Rev)] }

or more compactly,

arr4 = arr.sort_by { |i|
[i[0], (i[7..10]+i[4..5]+i[1..2]+i[11..15]).extend(Rev)]
}

To be really cute, let's define 'negative strings':

class String
def -@
if kind_of? Rev
String.new(self)
else
extend Rev
end
end
end

arr5 = arr.sort_by { |i|
[i[0], -(i[7..10]+i[4..5]+i[1..2]+i[11..15])]
}

Regards,

Brian.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,998
Messages
2,570,242
Members
46,834
Latest member
vina0631

Latest Threads

Top