numeric sort on string like a123-3

F

filippo

Hi,
I have string lilke these

a12-1
b1-3
b123-2
c12
c12-1

axxx-y

a is a letter
xxx is a number 1-120
y is a number 1-3

I want to sort by xxx, is it possible?
 
J

John W. Krahn

filippo said:
I have string lilke these

a12-1
b1-3
b123-2
c12
c12-1

axxx-y

a is a letter
xxx is a number 1-120
y is a number 1-3

I want to sort by xxx, is it possible?

my @sorted = map $_->[ 1 ],
sort { $a->[ 0 ] <=> $b->[ 0 ] }
map { /(\d+)/, $_ }
qw/ a12-1 b1-3 b123-2 c12 c12-1 /;



John
 
P

Paul Lalli

filippo said:
I have string lilke these

a12-1
b1-3
b123-2
c12
c12-1

axxx-y

a is a letter
xxx is a number 1-120
y is a number 1-3

I want to sort by xxx, is it possible?

Sure it is. In your sort subroutine, compare the xxx parts of the
string, rather than the strings themselves:

my @sorted = sort {
my ($a_num) = $a =~ /^[a-z](\d+)/;
my ($b_num) = $b =~ /^[a-z](\d+)/;
return $a_num <=> $b_num;
} @strings;

Or, to make this more efficient, use a Schwartzian Transform, so you
only have to do the pattern match once on each element:

my @sorted = map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [$_, /^[a-z](\d+)/ ] } @strings;

(Note that both of these will leave a12-1, c12, and c12-1 in a random
order in Perl 5.6 and lower, and in the same order as they were in the
original list in Perl 5.8 and higher. Altering the sort to take the
second number and/or the beginning letter into account is left as an
excercise to the OP. :) )

Paul Lalli
 
A

anno4000

filippo said:
Hi,
I have string lilke these

a12-1
b1-3
b123-2
c12
c12-1

axxx-y

a is a letter
xxx is a number 1-120
y is a number 1-3

I want to sort by xxx, is it possible?

Sure. Your xxx is the first group of digits in each list element, so
the match

/(\d+)/

will capture them. So this should sort them:

sort {
my ( $n_a) = $a =~ /(\d+)/;
my ( $n_b) = $a =~ /(\d+)/;
$n_a <=> $n_b;
} @list;

This supposes that all list elements have at least one group of
integers.

It also does unnecessary work since the numeric part is extracted
from each element every time, often multiple times for the same
element. A Schwartz transform eliminates the overhead:

map $_->[ 0],
sort { $a->[ 1] <=> $b->[ 1] }
map [ $_, /(\d+)/],
@list;

(Code untested)

Anno
 
U

Uri Guttman

JWK> my @sorted = map $_->[ 1 ],
JWK> sort { $a->[ 0 ] <=> $b->[ 0 ] }
JWK> map { /(\d+)/, $_ }

you forgot to return an anon array from that map:

map { [ /(\d+)/, $_ ] }

and since that is a simple expression you can lose the {} (but add a ,)

map [ /(\d+)/, $_ ],

JWK> qw/ a12-1 b1-3 b123-2 c12 c12-1 /;


i figure you know that but typoed.

this is one reason i recommend sort::maker for even simple sorts as you
don't have to worry about map issues and [0] vs [1] and such. you can
even have it return the source it generates and paste that into your
code so you are not dependent on the module being around.

uri
 
T

Ted Zlatanov

On 18 Jul 2006, (e-mail address removed) wrote:

filippo wrote: >
I have string lilke these

a12-1
b1-3
b123-2
c12
c12-1

axxx-y

a is a letter
xxx is a number 1-120
y is a number 1-3

I want to sort by xxx, is it possible?

my @sorted = map $_->[ 1 ],
sort { $a->[ 0 ] <=> $b->[ 0 ] }
map { /(\d+)/, $_ }
qw/ a12-1 b1-3 b123-2 c12 c12-1 /;

An alternate, using split:

my @sorted = map { $_->[0] . $_->[1] }
sort {$a->[1] <=> $b->[1] }
map { [split("", $_, 2)] }
qw/ a12-1 b1-3 b123-2 c12 c12-1 /;

avoids regexes but it's not exciting otherwise :)

Ted
 
P

Paul Lalli

Ted said:
An alternate, using split:

my @sorted = map { $_->[0] . $_->[1] }
sort {$a->[1] <=> $b->[1] }
map { [split("", $_, 2)] }
qw/ a12-1 b1-3 b123-2 c12 c12-1 /;

avoids regexes but it's not exciting otherwise :)

It also causes "is not numeric" warnings all over the place.

Paul Lalli
 
T

Ted Zlatanov

An alternate, using split:

my @sorted = map { $_->[0] . $_->[1] }
sort {$a->[1] <=> $b->[1] }
map { [split("", $_, 2)] }
qw/ a12-1 b1-3 b123-2 c12 c12-1 /;

avoids regexes but it's not exciting otherwise :)

It also causes "is not numeric" warnings all over the place.

Warnings? Who programs with -w on? :)

It does teach something about Perl regardless: a string that begins
with a number will be interpreted as that number despite the warning
in a numeric context. That can be useful in many places. Take it as
a fun example, not production code.

Ted
 
F

filippo

(megasnip)

wow, thank you very much to all you guys!

The sort routine is one of the perl stuff that I wasn't able to fully
understand, now I have something to study :)


Thanks again,

Filippo
 
J

John W. Krahn

Uri said:
JWK> my @sorted = map $_->[ 1 ],
JWK> sort { $a->[ 0 ] <=> $b->[ 0 ] }
JWK> map { /(\d+)/, $_ }

you forgot to return an anon array from that map:

map { [ /(\d+)/, $_ ] }

and since that is a simple expression you can lose the {} (but add a ,)

map [ /(\d+)/, $_ ],

JWK> qw/ a12-1 b1-3 b123-2 c12 c12-1 /;


i figure you know that but typoed.

Oops. Thanks ;)



John
 
F

filippo

Paul Lalli ha scritto:
(Note that both of these will leave a12-1, c12, and c12-1 in a random
order in Perl 5.6 and lower, and in the same order as they were in the
original list in Perl 5.8 and higher. Altering the sort to take the
second number and/or the beginning letter into account is left as an
excercise to the OP. :) )

Hi Paul, thanks for the opportunity to develope my brain but I confess
that I could not succeed :)
I'd like to have them sorted on the minor numeric, es

a12
a12-1
a12-2
a12-3
a13

could you give me at least a hint?
Thanks

Filippo
 
G

Gunnar Hjalmarsson

filippo said:
Hi Paul, thanks for the opportunity to develope my brain but I confess
that I could not succeed :)

BS. Use the docs (perldoc -f sort) and make an attempt.
 
T

Tad McClellan

filippo said:
Paul Lalli ha scritto:

Hi Paul, thanks for the opportunity to develope my brain but I confess
that I could not succeed :)
I'd like to have them sorted on the minor numeric, es

a12
a12-1
a12-2
a12-3
a13

could you give me at least a hint?


my @sorted = map { $_->[0] }
sort { $a->[1] cmp $b->[1] or
$a->[2] <=> $b->[2] or
$a->[3] <=> $b->[3]
}
map { [$_, /^([a-z])(\d+)-?(\d*)/ ] } @strings;
 
F

filippo

Tad McClellan ha scritto:
my @sorted = map { $_->[0] }
sort { $a->[1] cmp $b->[1] or
$a->[2] <=> $b->[2] or
$a->[3] <=> $b->[3]
}
map { [$_, /^([a-z])(\d+)-?(\d*)/ ] } @strings;

thanks Tad,

my problem is a lot of warnings like these

Use of uninitialized value in string comparison (cmp) at C:\work\cs.pl
line 5291.
Argument "" isn't numeric in numeric comparison (<=>) at C:\work\cs.pl
line 5291.

I forgot to mention that I have also strings
bungalow 1
bungalow2
a12-1
a12

etc

Thanks,

Filippo
 
D

Dr.Ruud

filippo schreef:
I forgot to mention that I have also strings
bungalow 1
bungalow2
a12-1
a12

etc

You are fined with 3 weeks of serious contemplation. Enjoy, and don't
hesitate to come back after that.
 
T

Tad McClellan

filippo said:
Tad McClellan ha scritto:
my @sorted = map { $_->[0] }
sort { $a->[1] cmp $b->[1] or
$a->[2] <=> $b->[2] or
$a->[3] <=> $b->[3]
}
map { [$_, /^([a-z])(\d+)-?(\d*)/ ] } @strings;

thanks Tad,

my problem is a lot of warnings like these

Use of uninitialized value in string comparison (cmp) at C:\work\cs.pl
line 5291.
Argument "" isn't numeric in numeric comparison (<=>) at C:\work\cs.pl
line 5291.

I forgot to mention that I have also strings
bungalow 1
bungalow2


Your specification keeps changing, so the solution will keep changing.

This is very frustrating to folks who spend time on an answer that
cannot be used, because the initial specification was not well
thought out.

You've already used up all of your coupons, I do not care to spend
anymore time on chasing a problem that will not sit still.

Good luck with it.
 
T

Ted Zlatanov

I forgot to mention that I have also strings
bungalow 1
bungalow2
a12-1
a12

Write a function that, given any string in your list, will produce a
floating-point number representing its sort position. Then sort based
on that function based on the abundant examples you've been given.

Consider this a learning experience. Always specify your problem
carefully, before you try to solve it, especially when you ask others
to help you. That's a big difference between adequate and good
programmers: the good programmer knows where he's going, not just how
to get places. Good luck.

Ted
 

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,744
Messages
2,569,479
Members
44,900
Latest member
Nell636132

Latest Threads

Top