Thread Hash values berechnen (8 answers)
Opened by perl-novice at 2013-04-15 23:21

payx
 2013-04-16 10:37
#167082 #167082
User since
2006-05-04
564 Artikel
BenutzerIn

user image
Hallo perl-novice,

ich versuche auch mal einen Vorschlag, in der Hoffnung, die Anforderung richtig verstanden zu haben. Ich vereinfache dahingehend, dass ich von einer Datei ausgehe, in der in jeder Zeile durch ein Leerzeichen getrennte String-Zahl-Tupel stehen, wobei ein String mehrmals vorkommen kann. (Die Beispiel-Eingabedatei habe ich unten im Script als DATA-Block angehängt.) Die Ausgabe soll zeigen, welche Zahl im Schnitt neben einem String steht.

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/perl

use strict;
use warnings;

my %sum;
my %count;

for my $row (<DATA>) {
    chomp($row);
    my ($string, $zahl) = split /\s+/, $row;
    $sum{$string} += $zahl;
    $count{$string} ++;
}

for my $string (sort keys %sum) {
    my $mittelwert = $sum{$string}/$count{$string};
    print "$string: $mittelwert\n";
}

__DATA__
foo 40
bar 41
baz 43
foo 44

Ich habe zwei Hashes, die beide die Strings als keys haben. Der eine bildet als value die Summe aus den Zahlen zu diesem String, der zweite zählt die Häufigkeit des Strings. Der Durchschnitt ist dann Summe/Häufigkeit. (Statt zwei Hashes zu machen, könnte man auch einen Hash of Hashrefs oder einen Hash of Arrayrefs aufbauen, aber so ist es erstmal einfacher, denke ich.)

In der ersten for-Schleife werden die beiden Hashes befüllt, in der zweiten wieder ausgelesen.

Perlish und bequem finde ich dabei, dass man nichts vordefinieren muss: $sum{$string} += $zahl; erzeugt beim erstmaligen Aufruf automatisch diesen key im Hash und setzt ihn für die folgende Addition von $zahl auf 0, sodass der value durch die Addition einfach auf $zahl gesetzt wird. Beim den folgenden Aufrufen wird die neue Zahl dann zur bisherigen hinzuaddiert. (Wenn zu dem neuen key nicht eine Zahl addiert sondern ein String angehängt würde, dann würde der value zunächst implizit auf einen empty-String gesetzt.)

Generell, wenn Werte verglichen (z.B. Duplikate gesucht) werden sollen ("Kommt der Wert x in (a..z) vor?", "Hatte ich diesen Wert schon einmal?" usw.), bietet es sich an, diesen Wert als key eines Hashes zu gebrauchen. Als solcher kann er nur einmal vorkommen. Um also z.B. in einer Schleife zu prüfen, ob ein String schon einmal vorgekommen ist, genügt if ($hash{$string}) { ... } (wenn der value einen wahren Wert hat, z.B. 1).

HTH
Grüße
payx

View full thread Hash values berechnen