2009-12-08 6 views
13

Ich habe zwei Arrays:Wie kann ich Arrays elementweise in Perl summieren?

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

Ich möchte Elemente beider Arrays zusammenzufassen wie neues zu erhalten

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

Kann ich es tun, ohne durch Arrays Looping?

+0

Sind die Zahlen immer 0 und 1? Wenn ja, könnten Sie das als Integer behandeln und einfach zwei ganze Zahlen addieren, um eine dritte ganze Zahl mit denselben Ziffern wie dieses Array zu erhalten. – Benj

+0

Offensichtlich geht das auch davon aus, dass die Anzahl der Ziffern gering ist. – Benj

+0

Es ist OK. Ich habe nur 0 und 1. –

Antwort

27

für Perl 5:

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

Funktioniert nicht für mich http://dpaste.com/130683/ –

+0

@ melco-man: Ich dachte, Sie wollten das Ergebnis in einem Verweis auf ein Array, sonst werden keine eckigen Klammern benötigt – catwalk

+0

Funktioniert nicht http://dpaste.com/130684/ –

8

Wenn Sie mit Perl 6:

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

Die Perl 6 Advent Calendar weitere Beispiele hat.

+0

Aber was ist mit Perl 5? –

+0

Siehe @catwalk für eine Perl 5-Implementierung. – rjstelling

+5

ist '<<+>>' der Hovercraft-Operator? – Ether

7

Grundsätzlich nein, man kann es nicht ohne „Durchschleifen-arrays“, weil Sie jedes Element beiden Arrays, um zugreifen muß, um sie zu summieren. Beide Antworten verstecken das Schleifen unter einer Abstraktionsebene, aber es ist immer noch da.

Wenn Sie Bedenken haben, über sehr große Arrays zu schleifen, ist es wahrscheinlich am besten, andere Möglichkeiten zu erwägen, die Summe auf dem neuesten Stand zu halten.

7

Was ist los mit dem Looping über Arrays? Das sind die Grundlagen.

@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

For-Schleifen? in Perl? Mein Gott, was machst du? – Ether

+3

ich weiß genau was ich mache. Ich mag es nicht, kompliziert zu denken, das ist alles. – ghostdog74

6

Sie haben einen C-Stil für die Schleife und pairwise gesehen. Hier ist eine idiomatische Perl for-Schleife und 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; 

Ich mag map und pairwise am besten. Ich bin mir nicht sicher, ob ich diese beiden Optionen bevorzuge. pairwise behandelt einige langweilige Details von Rohrleitungen für Sie, aber es ist kein eingebauter wie map. Auf der anderen Seite ist die Kartenlösung sehr idiomatisch und kann für einen Teilzeitperoper undurchsichtig sein.

Also, keine echten Gewinne für beide Ansatz. IMO, beide pairwise und map sind gut.

1

Wenn Sie wirklich Angst vor Schleifen haben, dann können Sie die Arrays binär zerhacken, die Paare summieren und dann das resultierende Array rekursiv neu zusammensetzen. Keine Schleife, und als Bonus erfahren Sie, wie ein Teil der Fast-Fourier-Transformation-Ableitung funktioniert.

+0

Verwenden Sie Rekursion statt Schleifen - gute Idee! – asjo

1

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

Oder:

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

Oder:

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

Or (in Perl 6):

@c = @a ^+ @b 
0

To (explizit) Looping zu vermeiden, hier ist eine Lösung, die Rekursion "statt" verwendet:

#!/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)); 
} 

Ausgang:

2 1 0 1 2 

Beachten Sie, dass use v5.20 bedeutet, dass Sie nicht use strict; use warnings zu schreiben, ich denken.

Entschuldigung/Kudos zu @parm für die Idee.

0

Ich bin mir nicht sicher, was Sie mit der Summe vorhaben, sobald Sie sie haben, aber Sie planen mehr Vektor-y-Typen, dann könnte Math :: Matrix eine gute Lösung sein.

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