in reply to Rule-based sorting

Actually, it sounds to me like the sort() command is precisely what you need. Don't forget, you can define your own sorting methods.

In fact, this looks like a job for the Schwartzian Transform. First, you parse out all your strings at once, like so:

$string1 = 'foo'; $string2 = 'bar'; @in_strings = ( 'blue15midget_bar', 'this is an exception', 'blue17midget_foo', 'deep13gizmonic_bar', 'another exception', 'red12dwarf_foo', 'red12dwarf_bar', 'exception containing _foo', ); %string_table = (); foreach my $in_string (@in_strings) { if ( $in_string =~ m{(.+) (\d{2,2}) (.+) _ ($string1 | $string2 ) +$ }x \ ) { $string_table{$in_string} = { initial => $1, number => $2 + 0, another => $3, ending => $4, }; } else { $string_table{$in_string} = 'EXCEPTION'; } }
Next, you write a sorting routine that checks these parsed strings.
%end_order = ( $string1 => 0, $string2 => 1, ); sub funky_sort { my $p_a = $string_table{$a}; my $p_b = $string_table{$b}; if ( ($p_a eq 'EXCEPTION') && ($p_b eq 'EXCEPTION') ) { return $p_a cmp $p_b; } elsif ( $p_a eq 'EXCEPTION' ) { return 1; } elsif ( $p_b eq 'EXCEPTION' ) { return -1; } else { $p_a->{ending} eq $p_b->{ending} or return ( $end_order{ $p_a-> +{ending} } <=> $end_order{ $p_b->{ending} } ); $p_a->{number} == $p_b->{number} or return ( -1 * ( $p_a->{number} <=> $p_b->{number} ) ); $p_a->{initial} eq $p_b->{initial} or return ( $p_a->{initial} cmp $p_b->{initial} ); $p_a->{another} eq $p_b->{another} or return ( $p_a->{another} cmp $p_b->{another} ); # If all of these are true, then the two are equal. return 0; } }
Then, finally, you can use sort() to sort these guys.
foreach my $string (sort funky_sort @in_strings) { print $string, "\n"; }
And your stuff is sorted! See the manual entry on sort().

Disclaimer: I've tested this code to make sure that it runs, but haven't run extensive tests on it. Double-checks are appreciated and recommended.

stephen

Replies are listed 'Best First'.
Re: Re: Rule-based sorting
by DeusVult (Scribe) on Apr 10, 2001 at 19:01 UTC

    You're my hero :)

    I've tested this out, and it seems to work very well. However, I am really confused about that, because it doesn't seem like it should even compile, much less work.

    First off, there are these lines:

    my $p_a = $string_table{$a}; my $p_b = $string_table{$b};

    Now, I checked, and those are the only times $a and $b are used. They are never declared (no my's anywhere!) and they are never given a value. It seems like use strict should hop all over this like a rapid chef with a meat cleaver, but it doesn't. Even still, it seems like you're assigning to $p_a and $p_b from empty variables, but yet they clearly receive values. So my response is "huh?" Are $a and $b some sort of special variables that result from sort, or is something even funkier going on?

    Also, &funky_sort only sorts two things. So when you call funky_sort @in_strings, it would seem that it would only sort the first two things, and leave the rest of the array alone. Of course, it doesn't do that at all, but why? Is it a consequence of calling sort first?

    So I really want to thank you for your help, and this truly cool scrap o' code. However, you really made my head hurt :)

    Some people drink from the fountain of knowledge, others just gargle.

      I'm not sure whay you're saying about funky_sort(), but as for $a and $b these are special variables in the context of doing a sort. see sort for a full explanation and a rather explicit warning about trying to declare them lexically. =)
      "A man's maturity -- consists in having found again the seriousness one had as a child, at play." --Nietzsche