2009-12-08 2 views
13

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

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

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

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

Могу ли я сделать это без зацикливания через массивы?

+0

Всегда ли цифры 0 и 1? Если это так, вы можете рассматривать это как целое число и просто добавить два целых числа вместе, чтобы дать вам третье целое число с теми же цифрами, что и этот массив. – Benj

+0

Очевидно, что также предполагается, что количество цифр невелико. – Benj

+0

Всё нормально. У меня только 0 и 1. –

ответ

27

для Perl 5:

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

Не работает для меня http://dpaste.com/130683/ –

+0

@ melco-man: Я думал, что вы хотите, чтобы результат был в ссылке на массив, иначе квадратные скобки не нужны – catwalk

+0

Не работает http://dpaste.com/130684/ –

8

Если вы используете 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 имеет больше примеров.

+0

Но как насчет Perl 5? –

+0

См. @catwalk для реализации Perl 5. – rjstelling

+5

'' <<+>> 'оператор на воздушной подушке? – Ether

7

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

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

7

что с этим связано с чередованием массивов? вот в чем основы.

@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"; 
} 
+9

Для петель? в Perl? Боже мой, что ты делаешь? – Ether

+3

Я точно знаю, что делаю. Мне не нравится думать сложно, вот и все. – ghostdog74

6

Вы видели стиль 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. С другой стороны, решение карты очень идиоматично и может быть непрозрачным для стороннего игрока.

Итак, никаких реальных побед для любого подхода нет. ИМО, как pairwise, так и map являются хорошими.

1

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

+0

Используйте рекурсию вместо цикла - отличная идея! – asjo

1

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); 

Or (в Perl 6):

@c = @a ^+ @b 
0

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

#!/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 за идею.

0

Я не уверен, что вы планируете делать с суммой, как только у вас есть это, но вы планируете делать больше вещей типа 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); 
Смежные вопросы