[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

A sort_by descending sort

Michael Gaunnac

10/8/2004 1:57:00 PM

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"]

Mike
8 Answers

Gavin Kistner

10/8/2004 2:01:00 PM

0

On Oct 8, 2004, at 7:57 AM, Michael Gaunnac wrote:
> 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 }

?

--
"When I am working on a problem I never think about beauty. I only
think about how to solve the problem. But when I have finished, if the
solution is not beautiful, I know it is wrong."
- R. Buckminster Fuller



Michael Gaunnac

10/8/2004 2:08:00 PM

0

Gavin Kistner wrote:
> On Oct 8, 2004, at 7:57 AM, Michael Gaunnac wrote:
>> 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


gabriele renzi

10/8/2004 2:19:00 PM

0

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 :)

Brian Candler

10/8/2004 2:32:00 PM

0

On Fri, Oct 08, 2004 at 10:57:20PM +0900, Michael Gaunnac wrote:
> 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.


Michael Gaunnac

10/8/2004 3:55:00 PM

0

gabriele renzi wrote:
> 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>


gabriele renzi

10/8/2004 4:11:00 PM

0

Michael Gaunnac ha scritto:

> gabriele renzi wrote:
>
>>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 :/

Mark Hubbart

10/8/2004 4:37:00 PM

0

On Sat, 9 Oct 2004 00:55:14 +0900, Michael Gaunnac
<mlgaunnac@hotmail.com> wrote:
>
>
> gabriele renzi wrote:
> > 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


Brian Candler

10/9/2004 3:47:00 PM

0

On Sat, Oct 09, 2004 at 12:55:14AM +0900, Michael Gaunnac wrote:
> # 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.