Sorting based on string value

Discussion in 'Perl Misc' started by Ninja67, Dec 4, 2006.

  1. Ninja67

    Ninja67 Guest

    I've got the following code in a script:

    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!
     
    Ninja67, Dec 4, 2006
    #1
    1. Advertising

  2. Ninja67

    Paul Lalli Guest

    Ninja67 wrote:
    > I've got the following code in a script:
    >
    > 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>


    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
     
    Paul Lalli, Dec 4, 2006
    #2
    1. Advertising

  3. Ninja67 wrote:
    > 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?


    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
     
    Gunnar Hjalmarsson, Dec 5, 2006
    #3
  4. On 12/04/2006 04:46 PM, Ninja67 wrote:
    > I've got the following code in a script:
    >
    > 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!
    >


    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);



    --
     
    Mumia W. (reading news), Dec 5, 2006
    #4
  5. On 12/04/2006 07:49 PM, Gunnar Hjalmarsson wrote:
    > Ninja67 wrote:
    >> 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?

    >
    > 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;
    >


    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.


    --
     
    Mumia W. (reading news), Dec 5, 2006
    #5
  6. Ninja67

    Uri Guttman Guest

    >>>>> "MW(n" == Mumia W (reading news) <> writes:

    >> 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 ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Dec 5, 2006
    #6
  7. Uri Guttman wrote:
    >>>>>>"MW(n" == Mumia W (reading news) writes:

    >
    > >> 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.


    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. :)

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Dec 5, 2006
    #7
  8. Ninja67

    Ninja67 Guest

    Gunnar Hjalmarsson wrote:
    > Ninja67 wrote:
    > > 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?

    >
    > 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


    You rock! That's awesome.
     
    Ninja67, Dec 5, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Boris Twila
    Replies:
    0
    Views:
    379
    Boris Twila
    Nov 14, 2006
  2. vikas
    Replies:
    3
    Views:
    525
    CBFalconer
    Aug 16, 2007
  3. padmagvs
    Replies:
    1
    Views:
    449
    cuffJ
    Aug 16, 2010
  4. Philipp Kraus

    sorting map value based

    Philipp Kraus, Nov 2, 2010, in forum: C++
    Replies:
    6
    Views:
    773
    Juha Nieminen
    Nov 7, 2010
  5. Aldric Giacomoni

    Sorting keys of hash based on value

    Aldric Giacomoni, Mar 22, 2010, in forum: Ruby
    Replies:
    4
    Views:
    148
    Robert Klemme
    Mar 22, 2010
Loading...

Share This Page