1

I'am new with perl and stucked with the following exercise. I have a multi-array and want order its element to descending to the inside arrays sum's. I want to make the order with Schwartzian transform.

This is my vector:

my @vectors = ( [1], [ 1, 2, 3 ], [4], [ 2, 2, 1 ] );

This is the expected vector:

@sorted_vectors = ( [1,2,3], [2,2,1], [4], [1] );

So far I am tried with these:

(1) #!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

my @vectors = ( [1], [ 1, 2, 3 ], [4], [ 2, 2, 1 ] );

my @sorted_vectors;

  # @sorted_vectors = ( [1,2,3], [2,2,1], [4], [1] );


my %hash=();
for(my $i=0;$i< scalar @vectors;$i++){

$hash{$i}=@vectors[$i];
}


for my $key ( sort { $hash{$b}[1] <=> $hash{$a}[1] } keys %hash ) {
    push(@sorted_vectors,[@{$hash{$key}}]);
}

 print Dumper( \@sorted_vectors );

(2)

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

my @vectors = ( [1], [ 1, 2, 3 ], [4], [ 2, 2, 1 ] );

my @sorted_vectors;

  # @sorted_vectors = ( [1,2,3], [2,2,1], [4], [1] );


my @sorted = map  { $_->[0] }
          sort { $a->[1] cmp $b->[1] }
          map  { [$_, foo($_)] }
               @vectors;

sub foo{
    my $res = 0;
    foreach my $x (@_) {
        $res+= $x;
    }
    return $res;

}

 print Dumper(\@sorted);
1
  • You'll want to change that cmp to <=> as you're comparing numbers. The cmp will only work as long as your totals are less than 10. Commented Nov 20, 2014 at 11:24

2 Answers 2

2

Your code works with few alterations,

my @sorted = map  { $_->[0] }
      # sort { $a->[1] cmp $b->[1] } # string sort, ascending order
      sort { $b->[1] <=> $a->[1] }   # numeric sort, descending order
      # map  { [$_, foo($_)] }       # foo() expects list, not array reference
      map  { [$_, foo(@$_)] }        # dereferencing $_ aref for foo()
           @vectors;

or same thing but using sum() from core module List::Util

use List::Util 'sum';
my @vectors = ( [1], [ 1, 2, 3 ], [4], [ 2, 2, 1 ] );

my @sorted_vectors = map $_->[0],
    sort { $b->[1] <=> $a->[1] }
    map [ $_, sum(@$_) ],
    @vectors;

use Data::Dumper; print Dumper \@sorted_vectors;

output

$VAR1 = [
      [
        1,
        2,
        3
      ],
      [
        2,
        2,
        1
      ],
      [
        4
      ],
      [
        1
      ]
    ];
Sign up to request clarification or add additional context in comments.

6 Comments

use List::Util 'sum'; my @sorted = sort { sum( @$b ) <=> sum( @$a ) } @vectors ;
@Zaid yes correct, note only that OP insisted on using ST.
See also List::UtilsBy::nsort_by, as per my answer
@LeoNerd +1 it is a shame that sort of utils isn't merged and in the core by now (always wanted max_by, min_by).
@mpapec: I maintain List::Util in core, so I'm open to suggestions for moving.
|
1

This is simple with List::UtilsBy::rev_nsort_by and List::Util::sum:

my @vectors = ( [1], [ 1, 2, 3 ], [4], [ 2, 2, 1 ] );

my @sorted = rev_nsort_by { sum @$_ } @vectors;

This sorts the list of @vectors in reverse numerical order (i.e. largest number first) of the result of its control block. The control block here simply sums all the individual elements of each component.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.