vitaly has asked for the wisdom of the Perl Monks concerning the following question:

Could you please help me with sorting by part of the string. For example I have array @xx = {dfb|cy|nmju, dfb|my|jhiho, ....) 1) I want to sort this array by the leading symbols up to | 2) from | to |, .... Thanks in advance, Vitaly

Replies are listed 'Best First'.
Re: sort array by part of the string
by Fletch (Bishop) on Dec 01, 2007 at 01:26 UTC

    Right off the bat, go read How (Not) To Ask A Question. Having said that:

    • that's not valid Perl so you haven't given anyone a decent idea of what exactly your data looks like
    • Read the docs on split (paying special attention to the fact that it takes a regular expression and keeping in mind that | is a special character inside a regex) and sort, and also search for "How do I sort an array by (anything)?" in "perldoc perlfaq4".

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: sort array by part of the string
by kyle (Abbot) on Dec 01, 2007 at 04:27 UTC

    Here's a quick implementation off the top of my head:

    my @xx = ( 'dfb|cy|nmju', 'dfb|my|jhiho', 'aaa|zz|gggg' ); my @sorted_xx = sort sorter @xx; print Dumper \@xx; print Dumper \@sorted_xx; sub sorter { my @arr_a = split /\|/, $a; my @arr_b = split /\|/, $b; while ( @arr_a ) { my $sa = shift @arr_a; my $sb = shift @arr_b; my $comparison = ( $sa cmp $sb ); return $comparison if $comparison; } return 0; } __END__ $VAR1 = [ 'dfb|cy|nmju', 'dfb|my|jhiho', 'aaa|zz|gggg' ]; $VAR1 = [ 'aaa|zz|gggg', 'dfb|cy|nmju', 'dfb|my|jhiho' ];

    I note that in the example strings you provide, the field delimiters are always in the same place (i.e., the fields are fixed length). If that's the case, you should be able to compare them directly without split, etc.

      Thanks, for your help. No delimeters are not in the same place, but the number of them is fixed:
      [^\|]*\|[^\|]*\|[^\|]*
Re: sort array by part of the string
by GrandFather (Saint) on Dec 01, 2007 at 04:49 UTC

    The canonical tool for sorting by a temporary (and possibly expensive to calculate) key is the Schwartzian Transform (See answers to When does it pay to use the schwartzian transform? and What is "Schwarzian Transform" (aka Schwartzian) or Super Search it yourself).

    The guts of the technique is to use map to generate a temporary array containing the original (unsorted) data and a key string. Use sort to sort the array by the key string, and another map to translate the sorted array back into the original (but now sorted) form.

    The code looks something like this:

    use strict; use warnings; my @array = qw(one4wobble two3wibble three2wig four1wog); @array = map {$_->[1]} # Convert back to original form sort {$a->[0] <=> $b->[0]} # Sort on the generated key map {[(/(\d+)/ ? $1 : -1), $_]} # Generate [key, data] pairs @array; print "@array";

    Prints:

    four1wog three2wig two3wibble one4wobble

    Perl is environmentally friendly - it saves trees