in reply to Sort then conditionally sort

There's no way to know whether to sort Y ascending or descending before X is fully sorted, so you'll need to do multiple passes.

use strict; use warnings; my @data; while (<DATA>) { chomp; push @data, [ split /\s+|,/ ]; } @data = sort { $a->[0] cmp $b->[0] || $a->[1] <=> $b->[1] } @data; my %order; my $last_f; my $last_x; for (@data) { if (!defined($last_f) || $last_f ne $_->[0]) { $order{$_->[0]}{$_->[1]} = +1; $last_f = $_->[0]; $last_x = $_->[1]; } if ($last_x ne $_->[1]) { $order{$_->[0]}{$_->[1]} = -$order{$last_f}{$last_x}; $last_x = $_->[1]; } } @data = sort { $a->[0] cmp $b->[0] || $a->[1] <=> $b->[1] || ( $a->[2] <=> $b->[2] ) * $order{$a->[0]}{$a->[1]} } @data; print("$_->[0] $_->[1],$_->[2]\n") for @data; __DATA__ ...

Update: By sorting only one dimension at a time, we can avoid multiple passes. It actually makes the program simpler:

use strict; use warnings; my %data; while (<DATA>) { chomp; my ($f,$x,$y) = split /\s+|,/; push @{ $data{$f}{$x} }, $y; } my @data; my $order = +1; for my $f (sort keys %data) { my $xs = $data{$f}; for my $x (sort { $a <=> $b } keys %$xs) { my $ys = $xs->{$x}; push @data, map [ $f, $x, $_ ], sort { $order * ( $a <=> $b ) } @$ys; $order *= -1; } } print("$_->[0] $_->[1],$_->[2]\n") for @data; __DATA__ ...

In both case, the data was

aaa 1,2 aaa 2,1 aaa 2,3 aaa 3,1 aaa 3,2 aaa 4,1 aaa 4,5 bbb 2,2 bbb 2,5 bbb 2,1 bbb 4,3 bbb 4,6 bbb 4,1 bbb 4,2 ccc 3,3 ccc 3,6 ccc 1,3 ccc 1,1 ccc 6,4 ccc 6,6 ccc 2,2 ccc 2,4

Replies are listed 'Best First'.
Re^2: Sort then conditionally sort
by lukez (Initiate) on Apr 10, 2009 at 17:18 UTC

    Global symbol "%data" requires explicit package name


    Ive been trying to figure out the file in/out code, but I get the error above, before getting to where the file in code even starts. Is something missing or not in correct order?

      My program doesn't generate that error. You'd get that error if you used hash %data without declaring it.
Re^2: Sort then conditionally sort
by lukez (Initiate) on Apr 10, 2009 at 04:22 UTC
    I want to thank all of you for your help on this . Hi ikegami, I think your (update code) will be easier for me to eventually understand than the other code versions. I am open to any explanation/comments 1 thing I need to mention is that the data will be in an external file. Do I need to change the way your code opens up data?
    That is this part

    while (<DATA>)
    to something like this???
    ========================================================
    open (my $IN, 'myfile.dat') or die "$!";
    my @data = <$IN>;
    close $IN;
    ========================================================
    I hope I am saying this correctly... I will also need to have all sorted data in a different file... I think something like
    open (my $OUT, ">", 'output.dat') or die "$!";
    then perhaps add $OUT to your print-output code
    print ("$_->[0] $_->1,$_->2\n") for @data;
    to
    print $OUT("$_->[0] $_->1,$_->2\n") for @data;
    would that work or am I out in left field? You guys a teriffic, thank you all again...

    by the way is perl the best method to do this? I am curious about why there are so many languages, if 3 or 4 can do it all....Not sure if that is true tho... thx so much everyone Luke

    pps Is there a way to know when I get a response from you guys, as in an email notice? peace!!!

      Why would think that reading a line from a file handle should be replaced with reading the entire file into an array and closing the file?

      By the way, my data wasn't exactly in the same format as yours. I thought the first column was actually a file name and not in the file itself. That means you'll need to adjust the input parsing and output format.

      would that work or am I out in left field?

      Yes, that's how you write to a file.

      I am curious about why there are so many languages, if 3 or 4 can do it all....

      Because no language does it all, or does it the same way.

        I was wondering how to get the <DATA> to be read in to this code. I wasnt familiar with this method. So you are saying that I can read the 2 col file line by line, with the code as is? So to invoke this code - do I do something like this> Let's say this code is saved as sort_it.pl
        Then from a cmd line I would type
        c:> perl sort_it.pl myinputfile.txt

        Is this close?
        thank you in advance...
        Im really trying to follow this stuff.