Re: How can I sort this data on the first field
by gaal (Parson) on Apr 25, 2005 at 06:57 UTC
|
my @sorted =
map { $_->[1] } # pick interesting data
sort { $a->[0] <=> $b->[0] } # sort numerically on first field
map { [ split /\|/, $_, 2 ] } # extract sortable field: $_->[0] i
+s sortable,
# $_->[1] i
+s data
<DATA>;
This is a simple variant of the Schwartzian Transform. Read it upwards.
In the original transform, the original data is kept around as one of the elements of @$_. Here I was assuming you didn't need to display the sort number — but if you did, then you need to do something slightliy different than a split. | [reply] [d/l] |
Re: How can I sort this data on the first field
by ColtsFoot (Chaplain) on Apr 25, 2005 at 06:55 UTC
|
Take a look at the Sort::Fields package
Sort::Fields provides a general purpose technique for efficiently sorting lists of lines that contain data separated into fields.
| [reply] |
Re: How can I sort this data on the first field
by prasadbabu (Prior) on Apr 25, 2005 at 06:57 UTC
|
If i understood your question correctly, is this you want,
while(<DATA>)
{
chomp;
@cpy=();
@cpy = split(/\|/);
$cpy{$cpy[0]} = [@cpy];
}
print "$_->[0]\t$_->[1]\n" for sort {$a->[0] <=> $b->[0]} values %cpy;
output:
30 microsoft
35 mozilla
40 opera
70 aol
76 netscape
updated:
| [reply] [d/l] [select] |
|
Thank you very much Prasad!
| [reply] |
Re: How can I sort this data on the first field
by Roy Johnson (Monsignor) on Apr 25, 2005 at 12:16 UTC
|
Since your numbers are the initial field, and are terminated by non-numbers, you can just treat the whole string as a number and Perl will Do The Right Thing:
print sort {$a <=> $b} <DATA>;
__DATA__
30|microsoft
70|aol
76|netscape
5|trouble?
35|mozilla
40|opera
No need for splitting or Schwartzian Transforms.
Caution: Contents may have been coded under pressure.
| [reply] [d/l] |
|
Roy Johnson's solution works, but it is not warning free. The original problem seems to me to scream out for the use of a hash. Here is how I would have approached the problem:
use strict;
use warnings;
print "Content-type: text/html\n\n";
my %someData;
while(<DATA>)
{
chomp();
(my $key, my $value) = split(/\|/, $_, 2);
$someData{$key} = $value;
}
foreach (sort { $a <=> $b } keys %someData)
{
print "$_\{$someData{$_}\}\n";
}
__DATA__
30|microsoft
70|aol
76|netscape
5|trouble?
35|mozilla
40|opera
100|FireFox
| [reply] [d/l] |
|
print "With Hash:\n\n";
$save = tell DATA;
while(<DATA>) {
my ($k, $v) = split '\|';
$hash{$k} = $v;
}
print "$_|$hash{$_}" for sort { $a <=> $b } keys %hash;
seek DATA, $save, 0;
print "\n\nWith array:\n\n";
while(<DATA>) {
my ($k, $v) = split '\|';
push @arr, [$k, $v];
}
print "$_->[0]|$_->[1]" for sort { $a->[0] <=> $b->[0] } @arr;
__DATA__
30|microsoft
70|aol
76|netscape
5|trouble?
35|mozilla
30|die microsoft
40|opera
100|FireFox
5|no more trouble
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: How can I sort this data on the first field
by tlm (Prior) on Apr 25, 2005 at 06:59 UTC
|
print "<table>\n";
print for
map sprintf( "<tr><td>%d</td><td>%s</td></tr>\n", @$_ ),
sort { $a->[ 0 ] <=> $b->[ 0 ] }
map { chomp; [ split /\|/ ] } <DATA>;
print "</table>\n";
| [reply] [d/l] |
Re: How can I sort this data on the first field
by salva (Canon) on Apr 25, 2005 at 08:35 UTC
|
use Sort::Key;
my @sorted = ikeysort { /^(\d*)/; $1 } @data;
or
my @sorted = ikeysort { no warnings; int $_ } @data;
or even
my @sorted = sort { no warnings; $a <=> $b } @data;
update:
oops, "no warnings" can not be used inside the comparison expression, so...
my @sorted;
{
no warnings;
@sorted = sort { $a <=> $b } @data;
}
... has to be used instead | [reply] [d/l] [select] |
Re: How can I sort this data on the first field
by TedPride (Priest) on Apr 25, 2005 at 07:29 UTC
|
I know there are several working examples above, but they all seem to be longer, more obfuscated, or don't include the creation code for the array. Props to the guy with the table code, though :) Here's mine.
use strict;
use warnings;
my ($c, @data);
while (<DATA>) {
chomp; $data[$c++] = [split /\|/];
}
print join('|', @$_) . "\n" for (sort {@$a[0] <=> @$b[0]} @data);
__DATA__
30|microsoft
70|aol
76|netscape
35|mozilla
40|opera
| [reply] [d/l] |
|
print sort <DATA>;
__DATA__
30|microsoft
70|aol
76|netscape
35|mozilla
40|opera
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] |
|
print sort <DATA>;
__DATA__
9|microsoft
70|aol
108|netscape
35|mozilla
40|opera
Based on the similarity of this example, with that in Need help with searching flatfile and updating it., I can only assume that the numbers aren't going to remain static. | [reply] [d/l] |
|
Re: How can I sort this data on the first field
by sh1tn (Priest) on Apr 25, 2005 at 09:31 UTC
|
my %sort = map{ /^(\d+)\|(\w+)/ and $1, $2 } <DATA>;
print "$_ - $sort{$_} \n" for sort keys %sort;
| [reply] [d/l] |
Re: How can I sort this data on the first field
by TedPride (Priest) on Apr 25, 2005 at 10:22 UTC
|
Chady: Yes, but that only works if the number remains exactly two characters long. I highly doubt that is the case. | [reply] |
|
What if you use
print sort {$a<=>$b} <DATA>;?
chas
(Update: Posted after reading an unrefreshed page and didn't
realize Roy Johnson had already suggested the same thing.)
| [reply] [d/l] |