perlunity.de - PERL | JAVASCRIPT | PHP | MySQL | APACHE



#!/COMMUNITY

Members: 5374
davon online: 1
weitere User: 29
Click for quality!




10.02.2012 / 20:42

Community-Member werden   |   Paßwort vergessen   |   OnlineMonitor (1) Wer ist online ... OnlineMonitor starten !
     

 

Home


PERLscripts


PHPscripts


JAVAscripts


Hilfreiches


Links2www


Newscenter


Community


Interna




Community  »  Perl: Allgemeines Forum zur Themenübersicht Themensuche Themenansicht in Thread-Modus


BeitragDoppelte Values in einem Hash ausgeben
Seitenanfang
Hi ,
ich würde gerne nur doppelte Elemente in einem Hash ausgeben und zwar so das die Value einmal ausgegeben wird und die jeweiligen Keys so oft sie auftreten.

Spricht

Key Value
Datei 1 A
Datei 2 B
Datei 3 C
Datei 4 D
Datei 5 A
Datei 6 C
Datei 7 B
Datei 8 C

gibt:

A
Datei 1
Datei 5

(nur einfach ein weiteres )

A
Datei 5
Datei 1

(sollte nicht sein)

B
Datei 2
Datei 7

C
Datei 3
Datei 6
Datei 8

D wird ignoriert kommt nur einfach vor.

Hier mal mein bisheriger Code:

#!/usr/bin/perl
use warnings;
#Hash hat später als Schlüssel die Dateinamen und als Wert die Sätze

my @textdateien=();
my @satz=();
my $zeile;
my %hash = ();
my $counter=0;
@textdateien =glob("dlf*.txt"); #Array für Textdateien

for (@textdateien)
{
s!\./!!g;
}

#Dateien einlesen (nur erste Zeile)
foreach my $file(@textdateien)
{
open (FILE, "< $file") or die "$!";
$zeile = <FILE>;
chomp($zeile);
push(@satz,$zeile);
}
close FILE;

my @Schluessel = @textdateien;
my @content = @satz;

#Hash aufbauen so dass der Schluessel die Dateinamen sind
#und die Werte die Zeilen
for $i (0 .. $#Schluessel) #für jeden eintrag in Schluessel
{
$hash{$Schluessel[$i]} = $content[$i]; # Wertzuweisung
}

my @elemente=@content; #Suchliste sind identisch mit den values
my @keys = keys %hash;
my @value =values %hash;

print "Sortierter Hash:\n";
foreach my $key(sort keys %hash) #Alle Schlüssel sortieren

{
my $wert=$hash{$key};

}

##############################################################################

print "GLEICHE ELEMENTE IM HASH\n\n";

foreach my $element_liste(@elemente) #Für alle Elemente der Suchliste
{
while ((my $schluessel,$wert) = each %hash) #Speichere Schluessel und Wert
{
if(@{$saetze_gefunden{$satz}}>=2)
if ($wert eq $element_liste) #Wenn Wert gefunden
{
print "$wert ($schluessel) , \n"; #gebe den Schlüssel aus
}

}

print "\n\n";
}

Er gibt mir hier aber alle aus auch die einzelnen und
oft auch die gleichen mehrfach.

Irgendne Idee?

Gruß
SkY

Datum: 30.05.2007-15:46

Beitragre: Doppelte Values in einem Hash ausgeben
Seitenanfang
achja habe ne falsche zeile

if(@{$saetze_gefunden{$satz}}>=2)

aus dem code ignorieren das muss raus hatte ich vergessen wegzumachen

aber ziemlich knifflige sachen gell?

Datum: 30.05.2007-15:50

Beitragre: Doppelte Values in einem Hash ausgeben
Seitenanfang
,,aber ziemlich knifflige sachen gell?''

Leider nicht :-( *g*

Du gehst die Werte vom original Hash '%data' durch, legst ein neues Key/Value-Paar in einen weiteren Hash '%data_dev' an so weit noch keins existiert und als Value nimmst du ein Array, in den du die Keys vom Ursprungshash pusht.


#!/usr/bin/perl

use strict;
use warnings;

my %data;
while(my $line = <DATA>) {
chomp($line);

my($key, $val) = split(/\t/, $line, 2);

$data{$key} = $val;
}

my %data_rev;
while(my($key, $val) = each %data) {
$data_rev{$val} ||= [];

push(@{$data_rev{$val}}, $key);
}

for my $key (sort keys %data_rev) {
print "$key\n";
print "\t$_\n" for @{$data_rev{$key}};
}

__DATA__
Datei 1 A
Datei 2 B
Datei 3 C
Datei 4 D
Datei 5 A
Datei 6 C
Datei 7 B
Datei 8 C

Code hab ich mir nicht weiter angeguckt.

Datum: 30.05.2007-22:25

Beitragre: Doppelte Values in einem Hash ausgeben
Seitenanfang
Danke ich schaus mir mal an.

Gruß
SkY

Datum: 30.05.2007-23:51

Beitragre: Doppelte Values in einem Hash ausgeben
Seitenanfang
@dash:

Leider sind die einfachen Werte auch noch mit dabei.

Gruß
SkY

Datum: 30.05.2007-23:59

Beitragre: Doppelte Values in einem Hash ausgeben
Seitenanfang
Entweder du entfernst die Hasheintraege mit nur einen Element im Array in dem du es durch 'grep' jagst oder du ueberspringst die Eintraege bei der Ausgabe.

Datum: 31.05.2007-01:10

Beitragre: Doppelte Values in einem Hash ausgeben
Seitenanfang
Hi, wie gehts das denn mit grep??
Ich kenne grep gar nicht.

Hättest du mir ein kurzes Beispiel?

Gruß
SkY

Datum: 07.06.2007-14:52

Beitragre: Doppelte Values in einem Hash ausgeben
Seitenanfang

grep AUSDRUCK, LISTE
grep CODEBLOCK, LISTE

grep fuehrt fuer jedes Element der LISTE den AUSDRUCK bzw. den CODEBLOCK aus, grep liefert dann, wenn das Ergebnis 'WAHR' ist, das Element zurueck oder laesst es aus.


my(@persons) = (
{ name => 'Frank',
age => 16 },
{ name => 'Susanne',
age => 21 },
{ name => 'Peter',
age => 32 },
);

my(@over_18) = grep { $_->{'age'} >= 18 } @persons;

print "$_->{'name'}\n" for @over_18;

Es gibt mehrere Varianten zu den gewuenschten Ergebnis zu kommen, grep ist nur die eine und das Ergebnis ist auch nicht der bereinigte Hash sondern eine Liste mit den Schluesseln (Keys) die doppelt vorkommende Werte haben bzw. umgekehrt,w ie man's wuenscht.

Diese Variante ist dann gut wenn man die Eintraege mit den nur einmal vorkommenden Werten fuer die spaetere Weiterverarbeitung noch benoetigt, man sie also aus den Hash nicht loeschen kann.

Die andere Variante verwendet delete() um die nicht mehr benoetigten Elemente aus dem Hash zu loeschen, auch hier gibt es wieder weitere Moeglichkeiten

Variante I:


delete($hash{$_}) for grep { @{$hash{$_}} < 2 } keys %hash;

Variante II:


(scalar @{$hash{$_}} < 2) and delete($hash{$_})
for keys %hash;

Variante III:


for(keys %hash) {
scalar(@{$hash{$_}}) > 1 and next;

delete($hash{$_});
}

Abgesehen von der reinen grep Variante (bei der du nur eine Liste der Schluessel erhaelst) unterscheiden sich die anderen von der Performance her kaum, dass heiszt man kann sich fuer die entscheiden die man fuer sich 'am besten lesbar' haelt.

Datum: 11.06.2007-13:13

-






-
-