Thread doppelte Zeilen (7 answers)
Opened by gmafx at 2010-02-26 16:44

topeg
 2010-02-27 03:08
#133757 #133757
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Ich habe dich da irgendwie falsch verstanden, ich dachte du hättest ein zweidimensionales Array:

Code (perl): (dl )
1
2
3
4
5
6
7
8
my @liste=(
  \@zeile1,
  \@zeile2,
  \@zeile3,
  \@zeile4,
  #...
  \@zeilen
)
Wobei man auf einen einzelnen Eintrag so zugreift:
Code (perl): (dl )
my $wert=$liste[$ZeilenNr]->[$SpaltenNr]


Du sagst nun aber du hast so was:
Code (perl): (dl )
1
2
3
4
5
6
7
8
my @liste=(
  $zeile1,
  $zeile2,
  $zeile3,
  $zeile4,
  #...
  $zeilen
)

wobei jede Zeile ein String ist.
Dann sind die Zeilen ja schon zu einem String zusammengefügt und du kannst die Sache mit dem Unique verweinfachen:
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# bitte immer strict und warnings nutzen,
# du bekommst dann bei vielen Fehlern Meldungen,
# die perl ansonsten versuchen würde zu interpretieren.
use strict;
use warnings;

# Dateiname der Datei,
# welche die Zeile enthält
# wie erstellst du die Datei?
# Ich vermute mal,
# dass du nicht immer eine Datei erstellen willst
# um eindeutige Zeilen zu bekommen, oder?
# Das ganze geht definitiv auch ohne Datei
my $file='test.tab';

# macht das selbe wie
# @liste = `cat test.tab`;
open(my $fh,'<',$file) or die("ERROR open $file ($!)");
my @liste=<$fh>;
close($fh);

# unique ist ein Hash
# ein Hash hat die Besonderheit,
# dass alle Schlüssel(keys genannt) einzigartig sind,
# dh, sie tauchen niemals doppelt auf.
# das ist soweit klar?
my %uniqe=();

# durchlaufe das Array rückwärts
for my $cnt (reverse (0..$#liste))
{
  # die Zeile die oben ausgelesen wurde
  my $line=$liste[$cnt];

  # entferne die Zeile aus dem Array wenn sie schon einmal gefunden wurde
  # wenn $line als Schlüssel in %unique schon mal vorgekommen ist ( "if($unique{$line})" ),
  # dann löschen wir die Zeile aus den Array @liste ( "splice(@liste, $cnt,1)" )
  splice(@liste, $cnt,1) if($uniqe{$line});

  # nun Zählen wir den Wert,
  # der zum Schlüssel $line gehört, um 1 hoch
  $uniqe{$line}++;
  # man kann hier auch schreiben:
  # $uniqe{$line}=1;

  # das gibt die Aktuelle Zeilennummer aus
  print "$cnt\n";
}

# alles testweise ausgeben:
for my $line (@liste)
{
  print $line;
}


2010-02-26T19:37:28 gmafx
Offensichtlich werden hier Datenstrukturen genutzt, die meinen Horizont überschreiten (ich kann Skalar, Array und ein Grundlagen mit Hashs, leider verstehe ich zB. nicht so etwas wie: $uniqe{$line}- sieht aus wie eine Referenz, oder? Dann muss man das auch wieder dereferenzieren, um es zu drucken, oder?

Du kennst doch Einen Hash mit Werten:
Code (perl): (dl )
1
2
3
4
my %hash=();
$hash{"bla"}=1;
$hash{'foo'}=1;
$hash{bar}=1;

Du kannst nun auch schreiben:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
my $wert='';
my %hash=();

$wert='bla';
$hash{$wert}=1;

$wert='foo';
$hash{$wert}=1;

$wert='bar';
$hash{$wert}=1;

wenn man das schreiben kann kann man auch das schreiben:
Code (perl): (dl )
1
2
3
4
5
6
7
my @liste=('bla','foo','bar');
my %hash=();

for my $wert (@liste)
{
  $hash{$wert}=1;
}

Soweit klar?

Nun benutze ich dies um die Eingelesene Zeile als Schlüssel für den Hash zu benutzen.

2010-02-26T19:37:28 gmafx
Zudem bedeuten beide Ansätze, dass ich die Struktur meiner Daten erst invertieren muss (ich habe die Spalten in einzelnen Arrays, jetzt brauche ich jeweils Reihe für Reihe als Element eines einzigen Arrays).

Da muss ich erst mal meine Daten "übersetzen".


Ich kann dir nicht folgen? Wie bitte ließt du die Zeilen denn nun?? Erst hast du Arrays und dann nicht?!
Machts du so was in der Art?
Code (perl): (dl )
1
2
3
4
5
while(my @line=read_line_von_irgendwo)
{
  my $zeilendaten=join(',',@zeile);
  push(@liste,$zeilendaten);
}


Wenn ja, kannst du dir das zusammenfügen sparen indem du eine Referenz auf das Array in @liste tust:
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
26
27
28
29
30
31
my @liste;

# ...

while( my @line=lese_zeilen_von_irgendwo() )
{
  my $zeilendaten=join(',',@zeile);
  push(@liste,[@zeile];
  # oder:
  # push(@liste,\@zeile;
}

# ...

# nun wollen wir nur die Zeilen, die einzigartig sind
my %uniqe=();
# durchlaufe das Array rückwärts
for my $cnt (reverse (0..$#liste))
{
  # ein String generieren der "eindeutig" ist
  my $line=join(',',@{$liste[$cnt]});
  # entferne die Zeile aus dem Array wenn sie schon einmal gefunden wurde
  splice(@liste, $cnt,1) if($uniqe{$line});
  # setze diese Zeile als gefunden;
  $uniqe{$line}++;
}

for(@liste)
{
  print join(', ',@$_)."\n";
}


aber bitte erkläre genauer wo und wie du die Daten ließt?

View full thread doppelte Zeilen