in reply to Sorting array with multiple values per keys

use Data::Dumper; use List::Util 'shuffle'; # randomized list my @a1 = shuffle ( '1,5', '3,9', '3,4', '6,2', '8,1' ); # convert to an array of hashes my @a2 = map { s/,/,y,/; s/\A/x,/; +{ split /,/ } } @a1; # sort 'x' values ascending and 'y' values descending my @a3 = sort { $a->{x} <=> $b->{x} || $b->{y} <=> $a->{y} } @a2; print Dumper \@a3; __END__ $VAR1 = [ { 'y' => '5', 'x' => 1 }, { 'y' => 9, 'x' => 3 }, { 'y' => 4, 'x' => 3 }, { 'y' => '2', 'x' => 6 }, { 'y' => '1', 'x' => 8 } ];

To understand the array of hashes, see perlreftut. See the documentation for sort and perlop to understand the <=> stuff in there. Of course, it'd be good to know map, split, and the fact that a list can be turned into a hash and back just by pretending that's what it is. You'd also be doing yourself a favor to learn about Data::Dumper and List::Util if you don't know of them already. They're core modules and awesome.

Replies are listed 'Best First'.
Re^2: Sorting array with multiple values per keys
by ikegami (Patriarch) on Aug 12, 2008 at 23:28 UTC

    my @a2 = map { s/,/,y,/; s/\A/x,/; +{ split /,/ } } @a1;
    is clearer as
    my @a2 = map { /(.*),(.*)/; ( x => $1, y => $2 ) } @a1;
    my @a2 = map { /(.*),(.*)/; { x => $1, y => $2 } } @a1;

    Update: Switched from parens to curlies as per reply.

      And it doesn't change @a1 as a side effect :)

      That is much easier to read, but it actually does something different. I think we'd rather have:

      my @a2 = map { /(.*),(.*)/; { x => $1, y => $2 } } @a1;

      Thanks!

Re^2: Sorting array with multiple values per keys
by cowgirl (Acolyte) on Aug 13, 2008 at 01:10 UTC
    Thanks for the great reply, guys. I chose to use this as a solution:
    my @Array = ( [1, 5], [6, 2], [3, 4], [3, 9], [8, 1], ); @Array = sort { $a->[0] <=> $b->[0] or $b->[1] <=> $a->[1] } @Array;
    It works great but how do I call the first element of the first element in the @Array now? Something like @Array[0]->[0] ? And can I still use foreach operators now? Like:
    foreach @Elements (@Array) { print @Elements[0]."x".@Elements[1]; }

      Like I already said,
      @Array[0]
      is inappropriate and produces a warning. Use
      $Array[0]->[0]
      or
      $Array[0][0]
      for short.

      foreach $Elements (@Array) { print $Elements->[0] . 'x' . $Elements->[1]; }
      Loop variables in foreach loops must be scalars, but scalars can be array references.