Ответ 1
для Perl 5:
use List::MoreUtils 'pairwise';
@sum = pairwise { $a + $b } @arr1, @arr2;
У меня есть два массива:
@arr1 = ( 1, 0, 0, 0, 1 );
@arr2 = ( 1, 1, 0, 1, 1 );
Я хочу суммировать элементы обоих массивов, чтобы получить новый, например
( 2, 1, 0, 1, 2 );
Могу ли я это сделать без перебора массивов?
для Perl 5:
use List::MoreUtils 'pairwise';
@sum = pairwise { $a + $b } @arr1, @arr2;
Если вы используете 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 есть больше примеров.
В принципе, нет, вы не можете сделать это без "перебора массивов", потому что вам нужно получить доступ к каждому элементу обоих массивов, чтобы их суммировать. Оба ответа до сих пор просто скрывают петлю под слоем абстракции, но он все еще там.
Если вы беспокоитесь о том, чтобы зацикливаться на очень больших массивах, лучше всего рассмотреть другие способы сохранения итоговой суммы, когда вы идете.
что не так с циклом над массивами? что основы.
@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";
}
Вы видели стиль 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
хороши.
Если вы действительно боитесь зацикливания, вы можете бинарно измельчать массивы, суммировать пары, а затем рекурсивно собирать результирующий массив. Нет циклов там, и в качестве бонуса вы узнаете, как работает часть преобразования преобразования fast-fourier.
Из 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
Чтобы избежать (явного) цикла, вот решение, которое использует рекурсию "вместо":
#!/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 за идею.
Я не уверен, что вы планируете делать с суммой, как только у вас есть это, но вы планируете делать больше вещей типа 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);