Как я могу суммировать элементы массива в Perl?

У меня есть два массива:

@arr1 = ( 1, 0, 0, 0, 1 );
@arr2 = ( 1, 1, 0, 1, 1 );

Я хочу суммировать элементы обоих массивов, чтобы получить новый, например

( 2, 1, 0, 1, 2 );

Могу ли я это сделать без перебора массивов?

Ответы

Ответ 1

для Perl 5:

use List::MoreUtils 'pairwise';
@sum = pairwise { $a + $b } @arr1, @arr2;

Ответ 2

Если вы используете Perl 6:

@a = (1 0 0 0 1) <<+>> (1 1 0 1 1)  #NB: the arrays need to be the same size

В Perl 6 Advent Calendar есть больше примеров.

Ответ 3

В принципе, нет, вы не можете сделать это без "перебора массивов", потому что вам нужно получить доступ к каждому элементу обоих массивов, чтобы их суммировать. Оба ответа до сих пор просто скрывают петлю под слоем абстракции, но он все еще там.

Если вы беспокоитесь о том, чтобы зацикливаться на очень больших массивах, лучше всего рассмотреть другие способы сохранения итоговой суммы, когда вы идете.

Ответ 4

что не так с циклом над массивами? что основы.

@arr1 = ( 1, 0, 0, 0, 1 );
@arr2 = ( 1, 1, 0, 1, 1 );
for ($i=0;$i<scalar @arr1;$i++){
    print $arr[$i] + $arr2[$i] ."\n";
}

Ответ 5

Вы видели стиль C для цикла и pairwise. Здесь идиоматический цикл Perl и map:

my @arr1 = ( 1, 0, 0, 0, 1 );
my @arr2 = ( 1, 1, 0, 1, 1 );

my @for_loop;
for my $i ( 0..$#arr1 ) { 
    push @for_loop, $arr1[$i] + $arr2[$i];
}

my @map_array = map { $arr1[$_] + $arr2[$_] } 0..$#arr1;

Мне нравится map и pairwise лучше всего. Я не уверен, что у меня есть предпочтение между этими двумя вариантами. pairwise обрабатывает некоторые скучные детали сантехники для вас, но он не является встроенным, как map. С другой стороны, решение карты очень идиоматично и может быть непрозрачным для стороннего игрока.

Итак, никаких реальных побед ни для одного подхода. IMO, как pairwise, так и map хороши.

Ответ 6

Если вы действительно боитесь зацикливания, вы можете бинарно измельчать массивы, суммировать пары, а затем рекурсивно собирать результирующий массив. Нет циклов там, и в качестве бонуса вы узнаете, как работает часть преобразования преобразования fast-fourier.

Ответ 7

Из http://www.perlmonks.org/?node_id=122393

@a = qw(1 2 3 4);
@b = qw(1 2 3 4);
@c = (); 

@c = map { $a[$_] + $b[$_] } ( 0 .. (@a > @b ? $#a : $#b) );

Или:

$c[@c] = $a[@c] + $b[@c] while defined $a[@c] or defined $b[@c];

Или:

$c[$_] = $a[$_] + $b[$_] for 0 .. (@a > @b ? $#a : $#b);

Или (в Perl 6):

@c = @a ^+ @b

Ответ 8

Чтобы избежать (явного) цикла, вот решение, которое использует рекурсию "вместо":

#!/usr/bin/perl

use v5.20;

my @arr1 = ( 1, 0, 0, 0, 1 );
my @arr2 = ( 1, 1, 0, 1, 1 );

my @result=non_looping_pairwise_sum([ @arr1 ], [ @arr2 ]); # pass in copies, so the originals are not modified
say "@result";

sub non_looping_pairwise_sum { # only handles lists that have the same length
    my ($a1, $a2)[email protected]_;

    return () if (scalar(@$a1)==0 and scalar(@$a2)==0);

    my $e1=shift @$a1;
    my $e2=shift @$a2;

    return ($e1+$e2, non_looping_pairwise_sum($a1, $a2));
}

Вывод:

2 1 0 1 2

Обратите внимание, что use v5.20 означает, что вам не нужно писать use strict; use warnings, я думаю.

Извинения/kudos @parm за идею.

Ответ 9

Я не уверен, что вы планируете делать с суммой, как только у вас есть это, но вы планируете делать больше вещей типа vector-y, тогда Math:: Matrix может быть в хорошей форме.

use Math::Matrix;

my $foo = Math::Matrix->new([ 1, 0, 0, 0, 1 ]);
my $bar = Math::Matrix->new([ 1, 1, 0, 1, 1 ]);
my $sum = $foo->add($bar);