Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Sorting numbers as strings

Reply
Thread Tools

Sorting numbers as strings

 
 
Jack Bauer
Guest
Posts: n/a
 
      05-18-2009
I'm trying to sort some strings containing numbers. The strings
themselves can't be changed (they're items being pulled from a DB.) This
is an example of some of the things I need to sort. First is how I
wanted them sorted:

FastEthernet0/1
FastEthernet0/10
FastEthernet0/11
FastEthernet0/12
FastEthernet0/13
FastEthernet0/2
FastEthernet0/3
FastEthernet0/4
FastEthernet0/5
FastEthernet0/6
FastEthernet0/7
FastEthernet0/8
FastEthernet0/9
...

I need to get it like this:
FastEthernet0/1
FastEthernet0/2
FastEthernet0/3
FastEthernet0/4
FastEthernet0/5
FastEthernet0/6
FastEthernet0/7
FastEthernet0/8
FastEthernet0/9
FastEthernet0/10
FastEthernet0/11
FastEthernet0/12
FastEthernet0/13

Then they could turn into FastEthernet1/1, etc. Also, the name doesn't
really matter as it could have FastEthernet, another name, or none at
all and just be 0/1 or whatever.

I'm guessing something like a regex to strip non-numbers so
FastEthernet0/1 becomes 01 then sort numerically, but that wouldn't help
if I have FastEthernet0/1, GigabitEthernet0/1, and FastEthernet0/2 since
it would come out in an incorrect order (01, 01, 02 instead of 01, 02,
01 because of the F and G alphabetical sort.)

Any ideas of the best way to go about this?
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Jack Bauer
Guest
Posts: n/a
 
      05-18-2009
Jack Bauer wrote:
> First is how I wanted them sorted:




Sorry I meant to say that the first version is how they're CURRENTLY
being sorted and the second version is how I WANT them sorted.
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Douglas Seifert
Guest
Posts: n/a
 
      05-18-2009
[Note: parts of this message were removed to make it a legal post.]

Maybe something like this:

irb> a = ["FastEthernet0/1", "FastEthernet0/10", "FastEthernet0/11",
"FastEthernet0/12", "FastEthernet0/13", "FastEthernet0/2",
"FastEthernet0/3", "FastEthernet0/4", "FastEthernet0/5", "FastEthernet0/6",
"FastEthernet0/7", "FastEthernet0/8", "FastEthernet0/9"]
irb> a.sort_by{|s| n,i = s.split('/'); [n, i.to_i]}
=> ["FastEthernet0/1", "FastEthernet0/2", "FastEthernet0/3",
"FastEthernet0/4", "FastEthernet0/5", "FastEthernet0/6", "FastEthernet0/7",
"FastEthernet0/8", "FastEthernet0/9", "FastEthernet0/10",
"FastEthernet0/11", "FastEthernet0/12", "FastEthernet0/13"]


On Mon, May 18, 2009 at 7:27 AM, Jack Bauer <(E-Mail Removed)> wrote:

> Jack Bauer wrote:
> > First is how I wanted them sorted:

>
>
>
> Sorry I meant to say that the first version is how they're CURRENTLY
> being sorted and the second version is how I WANT them sorted.
> --
> Posted via http://www.ruby-forum.com/.
>
>


 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      05-18-2009
2009/5/18 Jack Bauer <(E-Mail Removed)>:
> I'm trying to sort some strings containing numbers. The strings
> themselves can't be changed (they're items being pulled from a DB.) This
> is an example of some of the things I need to sort. First is how I
> wanted them sorted:
>
> FastEthernet0/1
> FastEthernet0/10
> FastEthernet0/11
> FastEthernet0/12
> FastEthernet0/13
> FastEthernet0/2
> FastEthernet0/3
> FastEthernet0/4
> FastEthernet0/5
> FastEthernet0/6
> FastEthernet0/7
> FastEthernet0/8
> FastEthernet0/9
> ...
>
> I need to get it like this:
> FastEthernet0/1
> FastEthernet0/2
> FastEthernet0/3
> FastEthernet0/4
> FastEthernet0/5
> FastEthernet0/6
> FastEthernet0/7
> FastEthernet0/8
> FastEthernet0/9
> FastEthernet0/10
> FastEthernet0/11
> FastEthernet0/12
> FastEthernet0/13
>
> Then they could turn into FastEthernet1/1, etc. Also, the name doesn't
> really matter as it could have FastEthernet, another name, or none at
> all and just be 0/1 or whatever.
>
> I'm guessing something like a regex to strip non-numbers so
> FastEthernet0/1 becomes 01 then sort numerically, but that wouldn't help
> if I have FastEthernet0/1, GigabitEthernet0/1, and FastEthernet0/2 since
> it would come out in an incorrect order (01, 01, 02 instead of 01, 02,
> 01 because of the F and G alphabetical sort.)
>
> Any ideas of the best way to go about this?


16:39:42 Temp$ ruby19 srt.rb
FastEthernet0/1
FastEthernet0/2
FastEthernet0/3
FastEthernet0/4
FastEthernet0/5
FastEthernet0/6
FastEthernet0/7
FastEthernet0/8
FastEthernet0/9
FastEthernet0/10
FastEthernet0/11
FastEthernet0/12
FastEthernet0/13
16:40:24 Temp$ cat srt.rb
puts DATA.sort_by {|s| s.scan(/\d+/).map {|x| x.to_i} }
__END__
FastEthernet0/1
FastEthernet0/10
FastEthernet0/11
FastEthernet0/12
FastEthernet0/13
FastEthernet0/2
FastEthernet0/3
FastEthernet0/4
FastEthernet0/5
FastEthernet0/6
FastEthernet0/7
FastEthernet0/8
FastEthernet0/9
16:40:28 Temp$

Kind regards

robert


--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

 
Reply With Quote
 
Jack Bauer
Guest
Posts: n/a
 
      05-18-2009
Douglas Seifert wrote:
> Maybe something like this:
> irb> a.sort_by{|s| n,i = s.split('/'); [n, i.to_i]}


Thanks to both of you guys. The one I quoted above looks similar to what
I was doing, I just thought it wasn't working because I'm using
pagination and it's ordering each page rather than the whole result and
then paginating.
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Rob Biedenharn
Guest
Posts: n/a
 
      05-18-2009

On May 18, 2009, at 10:40 AM, Robert Klemme wrote:

> 2009/5/18 Jack Bauer <(E-Mail Removed)>:
>> I'm trying to sort some strings containing numbers. The strings
>> themselves can't be changed (they're items being pulled from a DB.)
>> This
>> is an example of some of the things I need to sort. First is how I
>> wanted them sorted:
>>
>> FastEthernet0/1
>> FastEthernet0/10
>> FastEthernet0/11
>> FastEthernet0/12
>> FastEthernet0/13
>> FastEthernet0/2
>> FastEthernet0/3
>> FastEthernet0/4
>> FastEthernet0/5
>> FastEthernet0/6
>> FastEthernet0/7
>> FastEthernet0/8
>> FastEthernet0/9
>> ...
>>
>> I need to get it like this:
>> FastEthernet0/1
>> FastEthernet0/2
>> FastEthernet0/3
>> FastEthernet0/4
>> FastEthernet0/5
>> FastEthernet0/6
>> FastEthernet0/7
>> FastEthernet0/8
>> FastEthernet0/9
>> FastEthernet0/10
>> FastEthernet0/11
>> FastEthernet0/12
>> FastEthernet0/13
>>
>> Then they could turn into FastEthernet1/1, etc. Also, the name
>> doesn't
>> really matter as it could have FastEthernet, another name, or none at
>> all and just be 0/1 or whatever.
>>
>> I'm guessing something like a regex to strip non-numbers so
>> FastEthernet0/1 becomes 01 then sort numerically, but that wouldn't
>> help
>> if I have FastEthernet0/1, GigabitEthernet0/1, and FastEthernet0/2
>> since
>> it would come out in an incorrect order (01, 01, 02 instead of 01,
>> 02,
>> 01 because of the F and G alphabetical sort.)
>>
>> Any ideas of the best way to go about this?

>
> 16:40:24 Temp$ cat srt.rb
> puts DATA.sort_by {|s| s.scan(/\d+/).map {|x| x.to_i} }

<snip/>
>
> Kind regards
>
> robert
> --
> remember.guy do |as, often| as.you_can - without end
> http://blog.rubybestpractices.com/


If you do need to consider things like "FastEthernet..." v.
"GigabitEthernet...", then perhaps you want something like this which
breaks the original string into digits and non-digits and converts the
digits to be integers.

puts DATA.sort_by {|s| s.scan(/\d+|\D+/).map {|x| x =~ /\d+/ ?
x.to_i : x } }

-Rob

Rob Biedenharn http://agileconsultingllc.com
http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      05-18-2009
On 18.05.2009 17:37, Rob Biedenharn wrote:

> If you do need to consider things like "FastEthernet..." v.
> "GigabitEthernet...", then perhaps you want something like this which
> breaks the original string into digits and non-digits and converts the
> digits to be integers.
>
> puts DATA.sort_by {|s| s.scan(/\d+|\D+/).map {|x| x =~ /\d+/ ?
> x.to_i : x } }


Good point! Here's an interesting variant:

puts DATA.sort_by {|s| s.scan(/(\d+)|\D+/).map { $1 ? $1.to_i : $& } }

Kind regards

robert


--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
Reply With Quote
 
Rob Biedenharn
Guest
Posts: n/a
 
      05-19-2009

On May 18, 2009, at 1:01 PM, Robert Klemme wrote:

> On 18.05.2009 17:37, Rob Biedenharn wrote:
>
>> If you do need to consider things like "FastEthernet..." v.
>> "GigabitEthernet...", then perhaps you want something like this
>> which breaks the original string into digits and non-digits and
>> converts the digits to be integers.
>> puts DATA.sort_by {|s| s.scan(/\d+|\D+/).map {|x| x =~ /\d+/ ?
>> x.to_i : x } }

>
> Good point! Here's an interesting variant:
>
> puts DATA.sort_by {|s| s.scan(/(\d+)|\D+/).map { $1 ? $1.to_i : $& } }
>
> Kind regards
>
> robert
> --
> remember.guy do |as, often| as.you_can - without end
> http://blog.rubybestpractices.com/


Interesting, but "wrong" in that it doesn't sort the way the OP wanted.
Actually, since all the regexp applications have been applied by #scan
before the #map happens, the values of $1 and $& are effectively
constants and no sorting happens at all.

However, that did inspire me to make my version a little better.

puts DATA.sort_by {|s| s.scan(/(\d+)|(\D+)/).map {|(n,s)| s ||
n.to_i } }

I'd rather make the variables local than invoke the Perlish Regexp
globals (even if they did were assigned in the block the way you
expected). It could be even more readable if (n,s) were replaced with
(digits,nondigits), but it looks OK to me with n and s.

-Rob

Rob Biedenharn http://agileconsultingllc.com
(E-Mail Removed)


 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      05-19-2009
On 19.05.2009 02:55, Rob Biedenharn wrote:
> On May 18, 2009, at 1:01 PM, Robert Klemme wrote:
>
>> On 18.05.2009 17:37, Rob Biedenharn wrote:
>>
>>> If you do need to consider things like "FastEthernet..." v.
>>> "GigabitEthernet...", then perhaps you want something like this
>>> which breaks the original string into digits and non-digits and
>>> converts the digits to be integers.
>>> puts DATA.sort_by {|s| s.scan(/\d+|\D+/).map {|x| x =~ /\d+/ ?
>>> x.to_i : x } }

>> Good point! Here's an interesting variant:
>>
>> puts DATA.sort_by {|s| s.scan(/(\d+)|\D+/).map { $1 ? $1.to_i : $& } }


> Interesting, but "wrong" in that it doesn't sort the way the OP wanted.
> Actually, since all the regexp applications have been applied by #scan
> before the #map happens, the values of $1 and $& are effectively
> constants and no sorting happens at all.


Aaargh! Yes, you are completely right.

> However, that did inspire me to make my version a little better.
>
> puts DATA.sort_by {|s| s.scan(/(\d+)|(\D+)/).map {|(n,s)| s ||
> n.to_i } }
>
> I'd rather make the variables local than invoke the Perlish Regexp
> globals (even if they did were assigned in the block the way you
> expected). It could be even more readable if (n,s) were replaced with
> (digits,nondigits), but it looks OK to me with n and s.


Absolutely agree, I try to use local variables whenever possible.
Although I recently learned that $1 etc. are local to the current stack
frame! I did not knew that before and it certainly makes their use a
lot safer.

Thanks for catching my mistake!

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
Reply With Quote
 
Lars Christensen
Guest
Posts: n/a
 
      05-19-2009
On Mon, May 18, 2009 at 4:26 PM, Jack Bauer <(E-Mail Removed)> wrote:
> I'm trying to sort some strings containing numbers.


http://sourcefrog.net/projects/natsort/natcmp.rb

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
RE: sorting a list numbers stored as strings Delaney, Timothy (Tim) Python 4 09-25-2007 06:36 PM
sorting a list numbers stored as strings aine_canby@yahoo.com Python 6 09-25-2007 05:31 AM
Numbers to strings to numbers again one man army Javascript 6 12-30-2005 07:05 AM
Sorting of numbers or strings. Mars C Programming 3 03-02-2005 06:13 PM
Sorting strings with characters and numbers Carsten Zerbst Java 6 08-14-2003 08:36 PM



Advertisments