2 Arrays vergleichen
Peter Goss
- perl
Hallo Leute!
Ich bastle nun schon fast eine Woche an einem Perl-Script, was ich unbedingt bis Mittwoch endgültig zum Laufen gebracht haben muß. Vielleicht liegt es an der Uhrzeit oder den vielen Subscripts, die ich schon geschrieben habe, aber ich hab für folgendes Problem einfach keine Lösung.
Ich habe 2 Textdateien, die ich jeweils in 1 Array einlese. Hier mal ein Beispiel:
text1.txt:
1;PE12345
40;PE234
12;IK3210
text2.txt:
3;AK567
2;PE12345
20;IL098
6;JJ234567
Es handelt sich um 2 unterschiedliche Dateien, also die Eintragsanzahl je Datei kann vollkommen variieren,jedoch ist der Aufbau immer der selbe - an 1. Stelle immer eine Mengenanzahl und an 2. Stelle eine Registriernummer, jeweils mit einem Semikolion getrennt.
Ich möchte nun mittels eines Perl-Scriptes die beiden eingelesen Arrays miteinander vergleichen und in eine neue Datei zusammenfassen. Ist eine Registriernummer doppelt vergeben, sollen die beiden Mengen miteinander addiert werden und in die neue Datei gespeichert werden. Die anderen Einträge, also deren Registernummer nicht identisch sind, sollen aus beiden Dateien ebenfalls in die neue geschrieben werden.
Ich habe schon zahlreiche Versuche durchgespielt, aber leider erfüllt keiner seinen Zweck. Ich hoffe, von euch kann mir jemand helfen.
Ciao
Peter
Hallo Peter,
Ich habe schon zahlreiche Versuche durchgespielt, aber leider erfüllt
keiner seinen Zweck. Ich hoffe, von euch kann mir jemand helfen.
Zuerst musst du die Dateien in eine verwertbare Form ueberfuehren:
my ($file1,$file2) = ({},{});
read_file('datei1',$file1);
read_file('datei2',$file2);
sub read_file {
my $filename = shift;
my $ref = shift;
open DAT,'<'.$filename or die $!;
while(<DAT>) {
chomp;
next unless m!^(\d+);(.*)$!;
$ref->{$2} = $1;
}
close DAT;
}
Dann kannst du das ganze sehr einfach vergleichen:
my $merged = {};
foreach my $hash ($file1,$file2) {
foreach my $key (keys %{$hash}) {
$merged->{$key} = 0 unless exists $merged->{$key};
$merged->{$key} += $hash->{$key};
}
}
Die Keys sind die Serien-Nummern, die Values die Anzahl.
Grüße,
CK
Moin!
text1.txt:
1;PE12345
40;PE234
12;IK3210text2.txt:
3;AK567
2;PE12345
20;IL098
6;JJ234567
Hm.... Du musst einfach Dich einfach nur ganz dumm stellen und Dir vorstellen, Du wärst ein fürchterlicher Bürokrat... ich schreib Dir die Lösung mal in fastix® - Code :)
Einlesen der Textdateien in arrays. (Array1, Array2)
für jedes Element in Array1 {
trenne am ";" -> $anzahl1 , $rnr1;
für jedes Element in Array2 {
trenne am ";" -> $anzahl2 , $rnr2;
if ($rnr1==$rnr2) {
$anzahl1=$anzahl1+$anzahl2;
Element in Array2 löschen # (sic!)
}
Anhängen von $anzahl1; $rnr1 an neue Datei (oder Array)
}
} # es bleiben die Elemente in Array2, die keine Übereinstimmumg in Array1 hatten
für jedes Element in Array2 {
trenne am ";" -> $anzahl2 , $rnr2;
if (rnr2>0) {
Anhängen von von $anzahl1; $rnr1 an neue Datei (oder Array)
}
}
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®
Moin!
Einlesen der Textdateien in arrays. (Array1, Array2)
für jedes Element in Array1 {
trenne am ";" -> $anzahl1 , $rnr1;
für jedes Element in Array2 {
trenne am ";" -> $anzahl2 , $rnr2;
if ($rnr1==$rnr2) {
$anzahl1=$anzahl1+$anzahl2;
Element in Array2 löschen # (sic!)
} # end if
} # next element
Anhängen von $anzahl1; $rnr1 an neue Datei (oder Array);
} # es bleiben die Elemente in Array2, die keine Übereinstimmumg in Array1 hatten
für jedes Element in Array2 {
trenne am ";" -> $anzahl2 , $rnr2;
if (rnr2>0) {
Anhängen von von $anzahl1; $rnr1 an neue Datei (oder Array)
}
}
Da war eine Zeile verrutscht.
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®
hi fastix®!
danke, so in etwa habe ich mir das in etwa auch gedacht, nur auf die idee mit dem elementlöschen aus dem array ist mir nicht gekommen.
Element in Array2 löschen # (sic!)
hm, da hab ich das nächste problem. :( wie kann ich feststellen, welchen teil des arrays er in "foreach" gerade durchläuft, um es an "splice" zu übergeben?
Moin!
wie kann ich feststellen, welchen teil des arrays er in "foreach" gerade durchläuft, um es an "splice" zu übergeben?
Ich als alter BASIC- Programmierer gehe immer am liebsten Fußwege.
Ich baue ungern diese foreach- Schleifen...
Gefunden auf: http://www.perldoc.com/perl5.8.0/pod/perlintro.html#Conditional-and-looping-constructs
foreach (@array) {
print "This element is $_\n";
# Hier ist, was Du suchst: ^^
}
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®
Moin!
oder halt so:
$intCounter=(-1);
foreach (@array) {
$intCounter++; # <- Da ist, was Du suchst.
}
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®
Hallo fastix®,
$intCounter=(-1);
Bitte nicht.
my $intCounter = -1;
(-1) hat einen anderen Sinn als -1. Stichwort: Listen-Kontext.
Ansonsten sollte der OP einfach mal einen Blick auf meine Loesung
werfen... ;)
Grüße,
CK
Hallo fastix®,
Ansonsten sollte der OP einfach mal einen Blick auf meine Loesung
werfen... ;)
Nur, um das klarzustellen: das sollte er tun, weil meine Lösung einen
linearen Aufwand hat, während deine Lösung aufgrund des splice() nicht
mehr linear ist.
Grüße,
CK
Moin!
Hallo fastix®,
Deine sieht auch viel schöner aus. Im Ernst: Ich wollte eigentlich nur den Weg zeigen. Deswegen dieses fastix® - Script, welches eigentlich viel eher als Kommentar geeignet wäre. Mit Sicherheit lassen noch performantere Wege finden, zum Beispiel, wenn man die Array erstmal (extern... -> da war doch was) sortiert und dann die Durchläufe entsprechend abbricht. Aber
a) war ich ziemlich müde
b) wollte ich mich genau deswegen nicht mehr in die Sytax reindenken
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix®
Hallo fastix®,
Ich als alter BASIC- Programmierer gehe immer am liebsten Fußwege.
Ich baue ungern diese foreach- Schleifen...
Das solltest du ueberdenken. foreach-Schleifen sind idR um einiges
performanter als diese sog. 'Fußwege'.
Grüße,
CK
Moin!
text1.txt:
1;PE12345
40;PE234
12;IK3210text2.txt:
3;AK567
2;PE12345
20;IL098
6;JJ234567Ich möchte nun mittels eines Perl-Scriptes die beiden eingelesen Arrays miteinander vergleichen und in eine neue Datei zusammenfassen. Ist eine Registriernummer doppelt vergeben, sollen die beiden Mengen miteinander addiert werden und in die neue Datei gespeichert werden. Die anderen Einträge, also deren Registernummer nicht identisch sind, sollen aus beiden Dateien ebenfalls in die neue geschrieben werden.
Gehe ich recht in der Annahme, dass das in die neue Datei auszugebende Resultat (basierend auf obigen Daten, ergänzt durch meine Kommentare - die kommen natürlich nicht mit raus) so aussehen soll:
neutext.txt
3;PE12345 -> 2+1
40;PE234
12;IK3210
3;AK567
20;IL098
6;JJ234567
Sortierung ist egal?
Dann ist dein Problem kein "Array vergleichen"-Problem, sondern lediglich ein "Werte summieren"-Problem.
Zur Lösung eignet sich die Verwendung eines Hashes. Der Hash kriegt als Schlüssel deine Identifikationsnummer, und als enthaltenen Wert die Anzahl.
Auf diese Weise kannst du ganz einfach eine Datei nach der anderen auslesen und in den Hash füttern, und am Ende wiederum den Hash auslesen und in eine neue Datei füttern.
Also als Beispiel:
für alle Dateien (
öffne Datei
solange kein Dateiende (
lies eine Zeile.
splitte am ; -> ergibt $anzahl und $index
$hash[$index] = $hash[$index] + $anzahl
)
)
für alle Schlüsselwerte in %hash (
gib $anzahl und $index aus
)
Ja, alles in Pseudocode, aber ich schätze mal, du bist des Programmierens mächtig. Und bevor ich hier böse Perl-Fehler bastel oder my-Deklarationen vergesse, lasse ich es lieber (Perl ist nicht meine bevorzugte Programmiersprache).
- Sven Rautenberg
Hallo Sven,
[... Hash-Loesung ...]
[pref:t=68804&m=395246]
Nächste mal einfach alle Postings im Thread lesen ;)
Grüße,
CK
Moin!
[... Hash-Loesung ...]
[pref:t=68804&m=395246]
Nächste mal einfach alle Postings im Thread lesen ;)
Ich hab dein Posting sehr wohl gelesen. Sogar vor meinem Posting.
Dennoch denke ich, dass deine Lösung zwar vom Perl-Eleganz-Standpunkt aus einige Punkte machen würde, aber dennoch keine "gute Lösung[TM]" ist.
Die für Normalbenutzer absolut unverständlichen Perlismen mal außen vor gelassen - die sind ein Thema für sich, und vermutlich einer der Gründe, warum PHP so beliebt ist - , sehe ich in deiner Lösung die zentrierte Sicht auf zwei Dateien.
Nun kann man zwar jedes Problem von "mehrere Dateien zusammenfassen" zurückführen auf "Fasse die ersten zwei Dateien zusammen, und mache das Ergebnis zur neuen ersten Datei deiner Liste", das erscheint mir aber irgendwie etwas am Problem vorbei, weil man ja im Prinzip nicht immer nur zwei Dateien verarbeiten müßte.
Und ein wenig erklärende Worte machen sich auch nie schlecht in Lösungen. :)
- Sven Rautenberg