Re: Sorting an array of strings by number
by C-Keen (Monk) on Oct 01, 2001 at 16:00 UTC
|
Maybe a good idea would be using the sort SUBNAME LIST subroutine. With SUBNAME you specify a subroutine that will take care of comparing two elements and it will return depends on the outcome of the comparison. The Camel Book states the following sub for sorting numerically:sub numeric {$a <=> $b} The <=> operator will take care of everything! Of course you will need to change the above sub to fit exactly your needs, but that should be a piece of cake. :-) If not dare to ask again :-) Bye, C-Keen | [reply] [d/l] [select] |
Re: Sorting an array of strings by number
by tachyon (Chancellor) on Oct 01, 2001 at 16:03 UTC
|
You need to use a numeric sort (the default is alphabetic). Provided the numbers are at the start of the line you can just do this:
my @data = <DATA>;
my @alpha_sort = sort { $a cmp $b } @data;
my @numeric_sort = sort { $a <=> $b } @data;
print "Alpha sort\n@alpha_sort\n";
print "Numeric sort\n@numeric_sort\n";
__DATA__
123.45Hello
32.2World
1.5Just
288.2Another
288.3Perl
288.4Hacker
If you have more complex requirements then a Schwartzian transform will be in order.
cheers
tachyon
s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print
| [reply] [d/l] |
Re: Sorting an array of strings by number
by jeroenes (Priest) on Oct 01, 2001 at 16:05 UTC
|
There is more than one path to take here:
-
Zero-pad your numbers, so generate them
with
my $padded=sprintf("%08.3f",39.452);
You can do this while reading your data:
while (<>){
split /:/;
$_[0]=sprintf("%08.3f", $_[0]);
push @data, join ":", @_;
}
- Or you can sort numerically. This requires you to extract
the numbers and sort on them with <=> (see perlop), like
sort{ $a <=> $b} @numbers;
. You can write a sub
for the extraction:
sort{extract( $a ) <=> extract( $b )} @lines;
sub extract{
$a = shift;
split /:/, $a;
$_[0];
}
- It's better to extract your numbers, and use them as
keys in a hash, and work with a list of sorted keys:
my %hash;
while(<>){
my ($key, $data) = split( /:/, $_, 2 );
$hash{ $key } = $data;
}
print "Sorted!:\n\n", join "|", sort {$a <=> $b} keys %hash;
- .... many more paths to come up with
HTH, Jeroen
"We are not alone"(FZ)
(code untested, you'll get the idea)
Update
Albannach is right of course. Still, if you have quite some
data, a hash-lookup is more efficient. And more scalable,
as you can tie your hash onto a database,
e.g. To prevent that double-count problem, add a check in for
the key, if a double, add a counter or something.
$key .= ':001' if defined $hash{$key};
$key++ while defined $hash{$key};
| [reply] [d/l] [select] |
|
|
| [reply] |
Re: Sorting an array of strings by number
by MZSanford (Curate) on Oct 01, 2001 at 16:01 UTC
|
I would guess a custom sort black ... like the following test :
@a = qw(39 45 120 139);
@b = sort(@a);
@c = sort { $a <=> $b } @a;
print "B : ",join(',',@b),"\n"; # B : 120,139,39,45
print "C : ",join(',',@c),"\n"; # C : 39,45,120,139
"They shall not overcome. Whoever told them that the truth shall set them free was obviously and grossly unfamiliar with federal law."
-- John Ashcroft
| [reply] [d/l] |
Re: Sorting an array of strings by number
by Chady (Priest) on Oct 01, 2001 at 16:02 UTC
|
foreach $line (sort { (split /:/, $a)[0] <=> (split /:/, $b)[0] } @lis
+t){
...
He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.
Chady | http://chady.net/ | [reply] [d/l] |
Re: Sorting an array of strings by number
by suaveant (Parson) on Oct 01, 2001 at 17:28 UTC
|
Actually, you do not have to do the extra work of extracting the numbers from your strings if you do not want to. The way perl handles strings (IIRC) in a numeric context is it will take whatever it recognizes as a number off the front of the string, like in this example
print('1.01:dfsfda'+'1.34:kjlkljkj',"\n");
# prints 2.35\n
So, all you should need is the simple
@sorted = sort { $a <=> $b } @data;
- Ant
- Some of my best work - Fish Dinner
| [reply] [d/l] [select] |
|
|
my @sorted= do {
local( $^W )= 0;
sort { $a <=> $b } @data;
};
-
tye
(but my friends call me "Tye") | [reply] [d/l] |
|
|
my @sorted = do {
no warnings 'numeric';
sort { $a <=> $b } @data ;
};
| [reply] [d/l] |
|
|
Re: Sorting an array of strings by number
by broquaint (Abbot) on Oct 01, 2001 at 16:53 UTC
|
@res = sort { int($a) <=> int($b) } <DATA>;
print foreach(@res);
__END__
34:dsfalk:as4
2:asd:3425
67:dfa:srkwej9
98:erwvrklj:sek
output -
2:asd:3425
34:dsfalk:as4
67:dfa:srkwej9
98:erwvrklj:sek
This sorts the data according to the number in the first field, so pretty much what you're looking for right?
HTH
broquaint | [reply] [d/l] |
Schwartzian Transform, anyone?
by Fletch (Bishop) on Oct 02, 2001 at 19:21 UTC
|
@lines = (
q{23.40:hello:this:is:a:line},
q{123.38:this:is:another:line},
q{7.32895:yet:another:line},
);
@sorted = map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [ (split(/:/,$_))[0], $_ ] }@lines;
Of course, if you're going to split things anyhow, it might make just as much sense to go ahead and split the whole line and just use that.
@split = sort { $a->[0] <=> $b->[0] } map { [ split /:/ ] } @lines;
| [reply] [d/l] [select] |