[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Sorting a string...

Daniel Waite

10/31/2007 10:20:00 PM

I was porting a small Python script over to Ruby and realized Ruby does
not sort strings as I expected it would.

'cba'.sort # ["cba"]

So I wrote this...

class String

def sort
bytes = Array.new
self.each_byte { |byte| bytes << byte }
bytes.sort.collect { |byte| byte.chr }.join
end

end

'cba'.sort # "abc"

It's fairly clean, but I don't like the bytes = and self.each_byte bits.
It feels like there should be a way to say something like...

self.each_byte(&:collect).sort.collect { |byte| byte.chr }.join

Or something like that. I think some of the frustration comes from
Python seemingly being able to do this "out of the box." Unless, of
course, the following Python code generates an array of single
characters and not a single array with two strings (in which case Ruby
CAN do the same):

letters = list(state1 + state2) # I assume this is [ s1, s2 ]
letters.sort()
key = "".join(letters)

Any ideas?
--
Posted via http://www.ruby-....

15 Answers

David Mullet

10/31/2007 10:37:00 PM

0

Daniel Waite wrote:
> I was porting a small Python script over to Ruby and realized Ruby does
> not sort strings as I expected it would.
>
> 'cba'.sort # ["cba"]
>
> So I wrote this...
>
> class String
>
> def sort
> bytes = Array.new
> self.each_byte { |byte| bytes << byte }
> bytes.sort.collect { |byte| byte.chr }.join
> end
>
> end
>
> 'cba'.sort # "abc"
>
> It's fairly clean, but I don't like the bytes = and self.each_byte bits.
> It feels like there should be a way to say something like...
>
> self.each_byte(&:collect).sort.collect { |byte| byte.chr }.join
>
> Or something like that. I think some of the frustration comes from
> Python seemingly being able to do this "out of the box." Unless, of
> course, the following Python code generates an array of single
> characters and not a single array with two strings (in which case Ruby
> CAN do the same):
>
> letters = list(state1 + state2) # I assume this is [ s1, s2 ]
> letters.sort()
> key = "".join(letters)
>
> Any ideas?

class String
def sort
self.split('').sort.join
end
end

'cba'.sort #=> "abc"

--
Posted via http://www.ruby-....

Daniel Waite

10/31/2007 10:43:00 PM

0

David Mullet wrote:
> class String
> def sort
> self.split('').sort.join
> end
> end
>
> 'cba'.sort #=> "abc"

Brilliant! Thanks, David. I love this community. :)

I had tried split, but in haste, with no arguments. However, after
reading the docs again I see no arguments equals a space.

Interesting how the documentation has a perfect example:

"hello".split(//) #=> ["h", "e", "l", "l", "o"]

When writing that extension I kept thinking, all I need is an array, how
can I get one? Now I know!
--
Posted via http://www.ruby-....

David A. Black

10/31/2007 11:26:00 PM

0

Joel VanderWerf

10/31/2007 11:35:00 PM

0

David A. Black wrote:
> Hi --
>
> On Thu, 1 Nov 2007, Daniel Waite wrote:
>
>> I was porting a small Python script over to Ruby and realized Ruby does
>> not sort strings as I expected it would.
>>
>> 'cba'.sort # ["cba"]
>>
>> So I wrote this...
>>
>> class String
>>
>> def sort
>> bytes = Array.new
>> self.each_byte { |byte| bytes << byte }
>> bytes.sort.collect { |byte| byte.chr }.join
>> end
>>
>> end
>>
>> 'cba'.sort # "abc"
>
> I wouldn't overwrite a core method like that; you could end up with
> some very unexpected results. It's better to give it a different name.

Also, note that String#sort depends on String#to_a being defined, which
is no longer true in 1.9. It's kind of an accident that "cba".sort works
at all.

I guess that means someone will be free to implement String#sort, as
long as they stick to 1.9. Maybe there will be a core implementation
that works as expected?

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

7stud --

10/31/2007 11:39:00 PM

0

Daniel Waite wrote:
>
> letters = list(state1 + state2) # I assume this is [ s1, s2 ]

No. '+' is used for string concatenation in python just as it is in
ruby:

>state1 = "xxx"
>state2 = "AAA"
>letters = list(state1 + state2)

>output:--
>['x', 'x', 'x', 'A', 'A', 'A']
--
Posted via http://www.ruby-....

Konrad Meyer

10/31/2007 11:46:00 PM

0

Quoth Joel VanderWerf:
> David A. Black wrote:
> > Hi --
> >
> > On Thu, 1 Nov 2007, Daniel Waite wrote:
> >
> >> I was porting a small Python script over to Ruby and realized Ruby does
> >> not sort strings as I expected it would.
> >>
> >> 'cba'.sort # ["cba"]
> >>
> >> So I wrote this...
> >>
> >> class String
> >>
> >> def sort
> >> bytes = Array.new
> >> self.each_byte { |byte| bytes << byte }
> >> bytes.sort.collect { |byte| byte.chr }.join
> >> end
> >>
> >> end
> >>
> >> 'cba'.sort # "abc"
> >
> > I wouldn't overwrite a core method like that; you could end up with
> > some very unexpected results. It's better to give it a different name.
>
> Also, note that String#sort depends on String#to_a being defined, which
> is no longer true in 1.9. It's kind of an accident that "cba".sort works
> at all.
>
> I guess that means someone will be free to implement String#sort, as
> long as they stick to 1.9. Maybe there will be a core implementation
> that works as expected?
>
> --
> vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Well, anyone who's sorting a string really just wants to sort the component
letters, so my_str.split('').sort.join('') is the way to go. If they want to
add a method to String to simplify this, they can do that.

--
Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...

Brian Adkins

11/1/2007 2:51:00 AM

0

On Oct 31, 7:26 pm, "David A. Black" <dbl...@rubypal.com> wrote:
> On Thu, 1 Nov 2007, Daniel Waite wrote:
> > class String
> > def sort
> > end
> > end
>
> I wouldn't overwrite a core method like that; you could end up with
> some very unexpected results. It's better to give it a different name.

# splort for split sort ;)
def splort s
s.split('').sort!.join('')
end

John Joyce

11/1/2007 7:12:00 AM

0


On Oct 31, 2007, at 6:46 PM, Konrad Meyer wrote:

> Quoth Joel VanderWerf:
>> David A. Black wrote:
>>> Hi --
>>>
>>> On Thu, 1 Nov 2007, Daniel Waite wrote:
>>>
>>>> I was porting a small Python script over to Ruby and realized
>>>> Ruby does
>>>> not sort strings as I expected it would.
>>>>
>>>> 'cba'.sort # ["cba"]
>>>>
>>>> So I wrote this...
>>>>
>>>> class String
>>>>
>>>> def sort
>>>> bytes = Array.new
>>>> self.each_byte { |byte| bytes << byte }
>>>> bytes.sort.collect { |byte| byte.chr }.join
>>>> end
>>>>
>>>> end
>>>>
>>>> 'cba'.sort # "abc"
>>>
>>> I wouldn't overwrite a core method like that; you could end up with
>>> some very unexpected results. It's better to give it a different
>>> name.
>>
>> Also, note that String#sort depends on String#to_a being defined,
>> which
>> is no longer true in 1.9. It's kind of an accident that "cba".sort
>> works
>> at all.
>>
>> I guess that means someone will be free to implement String#sort, as
>> long as they stick to 1.9. Maybe there will be a core implementation
>> that works as expected?
>>
>> --
>> vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
>
> Well, anyone who's sorting a string really just wants to sort the
> component
> letters, so my_str.split('').sort.join('') is the way to go. If
> they want to
> add a method to String to simplify this, they can do that.
>
> --
> Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...
Presuming an English alphabetic order, perhaps yes.
What about case-sensitivity?
What about other languages? Ordering always depends on little
details. A basic English alphabetic ordering might be an overly
simple use-case. Although, it is a great example of a Ruby one-liner.
Remember unicode support is coming (we hope) to Ruby 2, and 1.9 is
really an unfinished 2.


Stefan Rusterholz

11/1/2007 10:19:00 AM

0

Daniel Waite wrote:
> I was porting a small Python script over to Ruby and realized Ruby does
> not sort strings as I expected it would.
>
> 'cba'.sort # ["cba"]
>
> So I wrote this...

If you just want to sort by byte-value (i.e. disregarding the
possibility of a multibyte-encoding and ignoring umlauts etc.), you can
do:
str.unpack("C*").sort.pack("C*")
It's about twice as fast as
str.split(//).sort.join

Regards
Stefan
--
Posted via http://www.ruby-....

Daniel Brumbaugh Keeney

11/1/2007 8:00:00 PM

0

On 10/31/07, Brian Adkins <lojicdotcom@gmail.com> wrote:

> # splort for split sort ;)
> def splort s
> s.split('').sort!.join('')
> end

The sort! is unnecessary, use sort (no exclamation)

-------------------------------------------
Daniel Brumbaugh Keeney
Devi Web Development
Devi.WebMaster@gMail.com
-------------------------------------------