取许多N大小的阵列的平均值

时间:2013-04-05 22:39:50

标签: arrays perl

任何人都可以帮我解决这个问题吗?我正在尝试编写一个占用许多N大小数组的脚本。在下面的示例中,自(1,2)(0+1+2+1)/4 = 1以来,数组的平均值为(2+3+2+1)/4 = 2。目前,下面的代码仅适用于大小为2的数组。我如何使用大小为100的数组执行此操作,以使@results的长度为100?我想我需要一个柜台吗?

use strict;
use warnings;

my @w = (0, 2);
my @x = (1, 3);
my @y = (2, 2);
my @z = (1, 1);

my @arrays = \(@w, @x, @y, @z);

my ($x, $y) = (0, 0);
foreach my $arr(@arrays) {
    $x += $arr->[0];
    $y += $arr->[1];
}

my @result = ( $x / @arrays,  $y / @arrays);

print "@result\n";  # <---- prints 1 2

#######
# my attempt
my @avg;
for my $i(0..$w) {
    # I'm guessing the result 'map...' returns is an array
    @avg[$i] = sum(\(map $_->[$i], @arrays)) / @arrays;    
}    

# sum the elements in an array and return its value
sub sum{
# takes 1 param: an arrey_ref
    my $sum = 0;
    for ( @{$_[0]} ) {
    $sum += $_;
    }
    return $sum;
}

我的尝试很接近,但不起作用。我想在不使用模块的情况下这样做。

5 个答案:

答案 0 :(得分:2)

这是我的解决方案:

use strict;
use warnings;

my $SIZE = 3;
my @w = (0, 2, 3);
my @x = (1, 3, 4);
my @y = (2, 2, 6);
my @z = (1, 1, 3);

my @arrays = \(@w, @x, @y, @z);

my @result = ();
foreach my $arr(@arrays) {
    for(my $i=0; $i<$SIZE; $i++) {
        $result[$i] += $arr->[$i];
    }
}

@result = map { $_ / @arrays } @result;

print "(@result)", "\n";  # <---- prints (1 2 4)

答案 1 :(得分:1)

以简单的方式做到这一点:

#!/usr/bin/env perl

use strict;
use warnings;

my @w = (1, 2, 3, 4);
my @x = (1, 2, 3, 4);
my @y = (1, 2, 3, 4);
my @z = (1, 2, 3, 4);

my @arrays = \(@w, @x, @y, @z);

my @sums;
foreach my $arr(@arrays) {
    for( my $i = 0; $i <= $#w; $i++, $j++ )
    {
    $sums[$j] += $arr->[$i];
    }
}

my @avg = map { $_ / @arrays } @sums;

foreach( @avg )
{
    print "$_ ";
}

print "\n";

答案 2 :(得分:1)

是的,非常接近。以下是问题代码的更正:

my @avg;
for my $i (0..$#w) {
    my @transposed = map {$_->[$i]} @arrays;
    $avg[$i] = sum(\@transposed) / @transposed;
    # or in one line: $avg[$i] = sum( [map {$_->[$i]} @arrays] ) / @arrays;
}

(我假设数组@w@x@y@z的大小都相同。)

请注意@avg[$i]是一个数组切片。您希望$avg[$i]指定特定位置。

答案 3 :(得分:1)

List::Util模块对于这样的问题非常有用。与简单的average子程序一起使它变得非常简单。

use strict;
use warnings;

use List::Util 'sum';
sub average { sum(@_) / @_ }

my @w = (0, 2);
my @x = (1, 3);
my @y = (2, 2);
my @z = (1, 1);

my @arrays = \(@w, @x, @y, @z);

my @results = map {
  my $i = $_;
  average(map $_->[$i], @arrays);
} 0 .. $#{$arrays[0]};

print "@results\n";

<强>输出

1 2

答案 4 :(得分:1)

map不会返回数组。 docs

更改

@avg[$i] = sum(\(map $_->[$i], @arrays)) /@arrays;

$avg[$i] = sum( map $_->[$i], @{$arrays[$i]} ) / @{$arrays[$i]};

并更改

sub sum{
    my $sum = 0;
    for ( @{$_[0]} ) {
    $sum += $_;
    }
    return $sum;
}

sub sum {
    my $sum;
    $sum += $_ for @_;
    return $sum;
}