Thread Eindeutige Liste aller Zeichen im String (32 answers)
Opened by roli at 2008-03-11 18:39

renee
 2008-03-14 13:41
#107045 #107045
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
grep liefert für alle Werte einer Liste (hier: @liste) die Elemente, für die das letzte Statement im Block (hier: ! $hash{$_}++) wahr ist.

Das grep hier ist im Prinzip folgender Code:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
my @neu = filter_liste();

sub filter_liste{
    my @neu;
    for( @liste ){
        # wenn Ausdruck wahr, dann schiebe das Element in das Array;
        if( ! $hash{$_}++ ){
            push @neu, $_;
        }
    }
    return @neu;
}


$hash{$_}++ zählt für den Schlüssel, der in $_ steht , den Wert um eins nach oben. Wenn der Schlüssel in dem Hash noch nicht existiert, wird er angelegt.

Mal ein Beispielcode:
Code (perl): (dl )
1
2
3
4
5
6
use Data::Dumper;
my %hash;
my @liste = qw(bla tata uhha tata);
for( @liste ){ print Dumper \%hash; $hash{$_}++};

print Dumper \%hash;


Ausgabe:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$VAR1 = {};
$VAR1 = {
'bla' => 1
};
$VAR1 = {
'tata' => 1,
'bla' => 1
};
$VAR1 = {
'uhha' => 1,
'tata' => 1,
'bla' => 1
};
$VAR1 = {
'uhha' => 1,
'tata' => 2,
'bla' => 1
};


Man sieht, dass der Hash am Anfang leer ist und dann wird in jedem Schleifendurchlauf der Schlüssel angelegt und der Wert auf 1 gesetzt (passiert durch das Inkrementieren mit ++). Der Schlüssel "tata" existiert bereits und da wird der Wert auf 2 inkrementiert.

Wichtig ist noch, dass es ein Post-Inkrement ist.

Vgl.:
Code (perl): (dl )
1
2
3
my $val = 0;
print $val++,"\n";
print ++$val;


Ausgabe:
Code: (dl )
1
2
0
2


Beim ersten Versuch wird das Inkrementieren erst nach dem print gemacht (deswegen Post-Inkrement). Also ist $val bei der Ausgabe noch 0 und erst nach dem Statement wird $val auf 1 erhöht. Beim zweiten Versuch ist das ganze ein Prä-Inkrement. Das heißt es wird erst hochgezählt und dann ausgegeben. Deswegen ist $val bei der Ausgabe 2.

Das Post-Inkrement liefert den Wert vor dem Hochzählen. Also liefert $hash{schluessel}++ eine "0" wenn der Schlüssel "schluessel" noch nicht existiert. Durch die Negation (!) wird der Ausdruck bei dem grep "wahr" wenn der Schlüssel noch nicht existiert. Existiert der Schlüssel schon, wird eine "1","2" oder sonst eine positive Zahl (je nachdem wie oft der Schlüssel schon vorkam) und das wäre ja eigentlich "wahr". Durch die Negation wird der Ausdruck aber "falsch" und somit liefert grep in diesem Fall nicht das Element.
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/

View full thread Eindeutige Liste aller Zeichen im String