ti-source has asked for the wisdom of the Perl Monks concerning the following question:

I have a search engine which takes each 'find' or search result from a database, calculates the percentage match, and takes all of the 'find' info and puts it all together into a string, which it adds to an array (each array item is a search result).

Example array:

@records = (".66+5638+copper globe",
            "1.00+1396+the blocks",
            ".33+4055+hunt draw");


As you might have guessed, this database has to do with geographic locations. The strings above are delimited using plus signs. The first item in each string is a decimal resulting from a match calculation ($words_found\$words_searched), which will be multiplied later in the script by 100, and a '%' character will be appended to this string when the match percentage will actually be displayed.

My problem is sorting the percentages. I obviously want the 100% match search results to appear before the 66%'s, 33%'s, or whatever. In older versions of this script, the 100% would come first, the 33% second, and 66% were last, for example.

I tried:

$a = 0; $b = 1;
@records = sort {$b <=> $a} @records;


but since they are strings with a bunch of other stuff in it, the script complained.

I don't want to rip the individual delimited strings apart to sort the array; its already a memory hogging script as it is.

Anyone have any ideas?

Thanks
  • Comment on Numerically sorting array items containing delimited strings

Replies are listed 'Best First'.
Re: Numerically sorting array items containing delimited strings
by davorg (Chancellor) on Nov 29, 2000 at 21:23 UTC

    I think you may have to split the strings, but by using a modified Schwartzian Transform you can do it in a pretty efficient manner. Try something like this:

    my @records = ('.66+5638+copper globe', '1.00+1396+the blocks', '.33+4055+hunt draw'); my @sorted = map { join '+', @$_ } sort { $a->[0] <=> $b->[0] } map { [ split /\+/ ] } @records;
    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

Re: Numerically sorting array items containing delimited strings
by chipmunk (Parson) on Nov 29, 2000 at 21:16 UTC
    How about:
    { local $^W; # or, in a recent version of Perl, no warnings; @records = sort { $b <=> $a } @records; }
(tye)Re: Numerically sorting array items containing delimited strings
by tye (Sage) on Nov 30, 2000 at 00:16 UTC

    @records = (".66+5638+copper globe", "1.00+1396+the blocks", ".33+4055+hunt draw");

    If you just convert your data to:

    @records = ("0.66+5638+copper globe", "1.00+1396+the blocks", "0.33+4055+hunt draw");
    then a reversed sort will do just what you want:
    s/^\./0./ for @records; @records= sort {$b cmp $a} @records;
    is one way to do that.

            - tye (but my friends call me "Tye")
Re: Numerically sorting array items containing delimited strings
by lemming (Priest) on Nov 29, 2000 at 21:38 UTC
    Chimpmunk's answer does work since a string in perl that begins with a number will act like a number in numeric situations.
    $str = "0.56HI There!"; $str += 10; # $str now is "10.56"
    That will set off warnings though. (as well it should)
    If you don't want to do a split, you can do this ugly piece of code.
    sub bypre { substr($b,0,index($b,"+")) <=> substr($a,0,index($a,"+")); }
    Update: Read Fastolfe's note and other people's suggestion of cmp
      Note that this is very expensive, since you're doing an index and substr on each element of the list MANY TIMES in the course of doing your sort. You're better off going with a transformation like those in the above posts, which only do the expensive stuff once.