my $cost_order = "A2yB";
my @series_cost = ();
for (@{$struct->{tree}->[0]->{rectangle}}) {
my $rec_string = "<table><tr><td ";
$rec_string .= ' meascode="'.$_->{meascode}.'"></td></tr></table>';
SWITCH: {
if ($_->{datafile} =~ /^cost/) { push(@series_cost, $rec_string);
last SWITCH; }
$nothing = 1;
}
}
Now that I have my array filled, I want to sort the contents of each
array by the "meascode" attribute. Each meascode attribute is a single
character that matches one of the characters in the $cost_order string.
How can I sort an array based on the order of the characters in the
$cost_order string?
So my array might contain:
<table><tr><td meascode="y"></td></tr></table>
<table><tr><td meascode="2"></td></tr></table>
<table><tr><td meascode="A"></td></tr></table>
<table><tr><td meascode="B"></td></tr></table>
but I need it to contain:
<table><tr><td meascode="A"></td></tr></table>
<table><tr><td meascode="2"></td></tr></table>
<table><tr><td meascode="y"></td></tr></table>
<table><tr><td meascode="B"></td></tr></table>
Thanks!
Maybe I'm not understanding your goal, but why aren't you just sorting
the values in your original array, before looping through them and
putting them inside strings in a new array? Why would you want to fill
the array, convoluting your value, then have to loop back through that
string, parse out the data you just put in, so that you can compare it?
Change:
> for (@{$struct->{tree}->[0]->{rectangle}}) {
To:
for (sort { $a->{meascode} cmp $b->{meascode} }
@{$struct->{tree}->[0]->{rectangle}}) {
Paul Lalli
One way:
my @series_cost = (
'<table><tr><td meascode="y"></td></tr></table>',
'<table><tr><td meascode="2"></td></tr></table>',
'<table><tr><td meascode="A"></td></tr></table>',
'<table><tr><td meascode="B"></td></tr></table>'
);
my $cost_order = 'A2yB';
my @sorted;
while ( my $mc = chop $cost_order ) {
unshift @sorted, grep /code="$mc"/, @series_cost;
}
print map "$_\n", @sorted;
--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
Use a hash table to store the values of y2AB and use that hash table to
help the sort comparison routine:
use strict;
use warnings;
use Data::Dumper;
my $count = 0;
my %cost_order = map +($_, $count++), qw(A 2 y B);
my @ms = map { meascode => $_ }, qw(y B 2 A);
my @series_cost = ();
for (@ms) {
my $rec_string = "<table><tr><td meascode='$_->{meascode}'>"
. " </td></tr></table>\n";
push @series_cost, $rec_string;
}
my @sorted = sort {
my @vals = "$a $b" =~ /meascode='([^']+)'/g;
$cost_order{$vals[0]} cmp $cost_order{$vals[1]};
} @series_cost;
print Dumper(\@sorted);
That's pretty cool. I almost wish I hadn't posted my own solution :-)
It took me a couple of minutes to figure it out because the 'sort'
function appears nowhere in the code. It's an insertion sort, and it
uses the $cost_order without creating an external hash or anything, and
it takes three lines--pretty good.
>> my @series_cost = (
>> '<table><tr><td meascode="y"></td></tr></table>',
>> '<table><tr><td meascode="2"></td></tr></table>',
>> '<table><tr><td meascode="A"></td></tr></table>',
>> '<table><tr><td meascode="B"></td></tr></table>'
>> my $cost_order = 'A2yB';
>> my @sorted;
>> while ( my $mc = chop $cost_order ) {
>> unshift @sorted, grep /code="$mc"/, @series_cost;
>> }
MW(n> That's pretty cool. I almost wish I hadn't posted my own solution :-)
MW(n> It took me a couple of minutes to figure it out because the 'sort'
MW(n> function appears nowhere in the code. It's an insertion sort, and it
MW(n> uses the $cost_order without creating an external hash or anything,
MW(n> and it takes three lines--pretty good.
and an insertion (or bubble) sort runs in O( N ** 2 ) which is very slow
for larger input lists.
given the above you can do this (tested):
use Sort::Maker ;
my @unsorted = (
'<table><tr><td meascode="y"></td></tr></table>',
'<table><tr><td meascode="2"></td></tr></table>',
'<table><tr><td meascode="A"></td></tr></table>',
'<table><tr><td meascode="B"></td></tr></table>',
) ;
my $sorter = make_sorter( 'GRT', string => qr/"(\w+)"/ ) ;
$sorter or die $@ ;
print map "$_\n", $sorter->( @unsorted ) ;
i agree that it would be better to sort the strings before adding the
html cruft but you can easily extract the key out of those strings with
a simple regex.
uri
--
Uri Guttman ------ u...@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
Yep, it's not recommended for larger lists.
> given the above you can do this (tested):
>
> use Sort::Maker ;
>
> my @unsorted = (
>
> '<table><tr><td meascode="y"></td></tr></table>',
> '<table><tr><td meascode="2"></td></tr></table>',
> '<table><tr><td meascode="A"></td></tr></table>',
> '<table><tr><td meascode="B"></td></tr></table>',
> ) ;
>
>
> my $sorter = make_sorter( 'GRT', string => qr/"(\w+)"/ ) ;
> $sorter or die $@ ;
>
> print map "$_\n", $sorter->( @unsorted ) ;
That's an efficient solution, but not to the OP's problem. :)
You rock! That's awesome.