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

Oops, I was not logged in when I posted this earlier. I have input in the following format "xx.xx.xx.xx 6 1 (ip number1 number2) and I cannot determine how to sort to sort it desending by the 3rd element. I found some code on Friday that almost worked but now I cant find it on perlmonks today. I have tried this but it does not print $a->2 when I try to print the values:
foreach ( CMP <INPUT> ){ print $_; } sub CMP { my($a0) = $a -> [2]; my($b0) = $b -> [2]; $b0 <=> $a0 }
This will print the data without a sort.
while (<INPUT>){ split ( $ip, $num1, $num2); printf "%18s %10s %10s\n", $ip, $num1, $num2 ; }
The code I found on Friday was something like this but I could not get it to work:
@sorted = map { $a->[2] cmp $b->[2] || $a->[2] <=> $b->[2] chomp; [split] <INPUT>}
Can someone please help? I have spent 3 hours trying to do something so simple. Kev

Replies are listed 'Best First'.
Re: sorting and array by [2]
by japhy (Canon) on Sep 23, 2002 at 14:30 UTC
    You're leaving out important steps. You need to 1) read in the file, 2) split it and put into an array ref, and 3) sort it.
    for (sort third_field <INPUT>) { print "Record: $_"; } sub third_field { my $x = (split ' ', $a)[2]; my $y = (split ' ', $b)[2]; $x <=> $y; }
    You might want to do a map-sort-map:
    for (by_third_field <INPUT>) { print "Record: $_"; } sub by_third_field { map $_->[0], sort { $a->[3] <=> $b->[3] } map { [ $_, split ] } @_; }

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: sorting and array by [2]
by kabel (Chaplain) on Sep 23, 2002 at 14:15 UTC
    your code looks quite weird. if you want to sort then use sort and not map! ;)
    @sorted = sort { $a->[2] <=> $b->[2] } <INPUT>; chomp (@sorted);
Re: sorting and array by [2]
by fruiture (Curate) on Sep 23, 2002 at 14:29 UTC

    Your question is quite unclear, not to say "gibberish" (but i don't use this word for a certain reason).

    Assuming you have an input-handle that serves the information you described linewise as "IP NUM1 NUM2" and you're reading that stuff into an array of arrays:

    while(<INPUT>){ chomp; push @array,[split]; }

    You'll only have to sort by the third element of each arrayref now:

    @sorted = sort { $a->[2] <=> $b->[2] } @array

    I can actually not see the problem, because each code example in your post is nonsense.

    --
    http://fruiture.de
Re: sorting and array by [2]
by kevyt (Scribe) on Sep 23, 2002 at 15:17 UTC
    Thanks to everyone. Japhy, I used your example:
    @info = function to read input ; for (sort third_field @info) { print "Record: $_"; } sub third_field { my $x = (split ' ', $a)[2]; my $y = (split ' ', $b)[2]; $y <=> $x; }
    I tried a sample similar to that but I had
    $a0 = $a -> [2]
    instead of
    $x = (split ' ', $a)[2];
    Thanks!!!
Re: sorting and array by [2]
by admiraln (Acolyte) on Sep 23, 2002 at 14:57 UTC
    I just want to comment on the line
    $a->[2] cmp $b->[2] || $a->[2] <=> $b->[2]
    If this was meant to be the sort subroutine, it has some problems (other than the aready mention ones). The or (||) is operating on the results of two comparison operators that return -1, 0 , 1. This will not a result that sort will be able to use. This will be interpreted as "Compare column 2 as text and if the elements are equal compare them as numbers". so it is still wrong. cmp is use for string and <=> is used for numbers. By the time you are executing the sort, you should know what the type is.

    Update: Based on this node : Q&A Node on multicolumn sorting and some other research I realized my orignal statment was not fully correct. The node does not mention that this works because the or operater (||) short circuits if not false. The whole expression returns the -1 or 1 value for the first sub expression that has non false value or return 0 if they are all equal. I guess a real monk should add this to the node.

Re: sorting and array by [2]
by kevyt (Scribe) on Sep 23, 2002 at 14:24 UTC
    Thanks Kabel, I tried this but it doesnt sort. I need a split somewhere but I am not sure where to place it. The data is read in by a function that places one line into [0] and the next line is in [1]. I placed <INPUT> where the function is for simplicity for the posting.
    @sorted = sort { $a->[2] <=> $b->[2] } <INPUT>; chomp (@sorted); foreach (@sorted){ print; print "\n"; }

    Edited: ~Mon Sep 23 15:53:50 2002 (GMT) by footpad: Replaced prose-based [ ] and < > characters with HTML entities for proper rendering.

Re: sorting and array by [2]
by kevyt (Scribe) on Sep 23, 2002 at 15:02 UTC
    Thanks, I'll give these a try. I guess I should have been more clear. I have several files with functions that read in the data and I left some of that code out because it would have made the posting huge. Then I placed a few samples of code I had tried to display what I could not get to work. I found a sample by by tadman that I almost got to work. Tadman's sample is below
    Re: How do you specify which fields to sort by when sorting an array. my @output = sort { $a->[0] cmp $b->[0] || $a->[3] <=> $b->[3] } map { chomp; [ split(',', $_, 4) ] } <INPUT_FILE>;