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:
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.)
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:
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.)
On Mon, May 18, 2009 at 7:27 AM, Jack Bauer <realmadrid2727@yahoo.es> 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/\.
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:
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.)
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 } }
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.
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 } }
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.
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 } }
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 } }
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.