Leser: 29
1
2
3
4
5
6
7
for (0 .. $#new_data) {
foreach my $old_data (@old_data) {
$new_data[$_] ne $old_data && next;
splice @new_data, $_, 1;
}
}
1 2 3 4 5 6
my @list = qw/eins zwei drei vier/; for my $foo ( 0 .. $#list ) { print "\$foo = $foo und \$#list = $#list\n"; push @list, $foo; }
2010-01-18T16:31:27 TaulmarillEr iteriert nicht über @new_data sondern über eine Liste von 0 bis $#new_data. Die wird beim ersten erreichen des Schleifenkopfes erzeugt und ändert sich danach nicht mehr.
Code (perl): (dl )1 2 3 4 5 6my @list = qw/eins zwei drei vier/; for my $foo ( 0 .. $#list ) { print "\$foo = $foo und \$#list = $#list\n"; push @list, $foo; }
1
2
3
4
5
6
7
8
for (0 .. $#new_data) {
! defined $new_data[$_] && last;
foreach my $old_data (@old_data) {
$new_data[$_] ne $old_data && next;
splice @new_data, $_, 1;
}
}
2010-01-18T21:57:17 pqwenn man über so eine liste iteriert und das array ändert, sollte man immer rückwärts drüberlaufen (mit reverse), dann passiert sowas nicht.
for (reverse 0 .. $#new_data) {
! defined $new_data[$_] && last;
2010-01-18T22:29:30 Escapeam einfachsten wäre wohl ein Hash-Splice (um Doppler zu filtern) aber ich habe die Befürchtung dass ich damit zuviel Speicher belege.
2010-01-18T22:47:25 pqwürdest du einen der arrays in einem hash ablegen, um im anderen duplikate zu löschen, würdest du, ich sag jetzt einfach mal, 3 mal soviel speicher verbrauchen, aber ein vielfaches an zeit sparen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
#!/usr/bin/perl -w use strict; use warnings; my %hash = (foo => defined, bar => defined, foobar => defined,); print "Altes \"Array\": " . (join ' ',keys (%hash)) . "\n"; local $/ = "\n"; while (<DATA>) { chomp; print "Untersuche $_..."; if (exists $hash{$_}) { print "haben wir schon\n" } else { print "nehmen wir\n"; $hash{$_} = defined } } print "Neues \"Array\": " . (join ' ',keys (%hash)) . "\n"; __DATA__ 0foo foo bar foofoo barbar foobar
2010-01-19T08:23:35 pqDer Datenbestand *ist* aber nicht in einem Hash abgelegt, sondern in einem Array.
2010-01-19T08:23:35 pqda nirgendwo irgendwelche Voraussetzungen für die Aufgabe gestellt wurden, möchte ich mich auch nicht weiter detailliert damit beschäftigen.
2010-01-19T08:23:35 pqWürde man eine Datenbank wie SQLite benutzen, könnte man vermutlich fast den ganzen Speicherverbrauch sparen.
2010-01-19T08:23:35 pqMir ging es darum, dass er 2 Arrays hat, und wenn er das eine noch zusätzlich in ein Hash legt, braucht das nochmal Speicher, und ein Hash braucht an sich immer noch etwas mehr als ein Array.
2010-01-19T08:37:38 biancaNun, der Datenbestand liegt nun mal tatsächlich *nicht* in einer Datenbank. Das Beispiel find ich jetzt gegenüber meinem wirklich zu abwegig.
2010-01-19T08:50:27 pqwie süss. du legst den datenbestand in ein hash ab, um meinen kommentar mit dem speicherverbrauch zu zerfetzen, aber wenn ich den datenbestand hypothetisch nach SQLite verlege, ist das zu abwegig.
2010-01-19T08:56:08 biancaNa ja, wenn in Deiner Umgebung ein Datenbestand von einer Datei in eine SQL DB genau so einfach überführt ist wie bei mir eine Datei in einen Hash statt in ein Array einzulesen dann ok.
2010-01-19T08:37:38 biancaWarum sollte jemand das über den Weg machen? Wie man Daten ablegt entscheidet man doch beim Einlesen und nicht irgendwann später, indem man nochmal umschaufelt von Array in Hash? Warum also sollte man Daten nicht gleich beim Einlesen im Hash ablegen?
2010-01-19T08:54:56 pqvielleicht, weil er die reihenfolge behalten will? nur mal so als beispiel.
1 2 3 4 5 6 7 8
for my $key ( keys %{{ a => 1, b => 2, c => 3, d => 4, }} ) { print "$key\n"; } # for
2010-01-19T16:15:35 MatthiasWEin Hash hat keine Reihenfolge.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
%hash = ( 1 => { a => '1', }, 2 => { b => '2', }, 3 => { c => '3', }, 4 => { d => '4', }, ); for my $key (sort {$a <=> $b} keys %hash) { print (grep {1} keys %{$hash{$key}}) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
%hash = ( a => { 1 => '1', }, b => { 2 => '2', }, c => { 3 => '3', }, d => { 4 => '4', }, ); for my $key ( sort { (keys %{$hash{$a}})[0] <=> (keys %{$hash{$b}})[0] } keys %hash ) { print "$key\n"; }
2010-01-19T17:32:08 MatthiasW2) Ist jetzt der Vorteil des Hashs verloren gegangen. Die von dir gezeigte Struktur hat (bei diesem Anwendungsfall) keine Vorteile gegenüber einem normalen Array.
2010-01-19T17:32:08 MatthiasW1) Haben Hashs so immer noch keine Reihenfolge. Es bleibt auch nicht schön ordentlich sortiert, sondern du sortierst die Schlüssel der ersten Ebene selbst.
2010-01-19T17:32:08 MatthiasW2) Ist jetzt der Vorteil des Hashs verloren gegangen. Die von dir gezeigte Struktur hat (bei diesem Anwendungsfall) keine Vorteile gegenüber einem normalen Array.
2010-01-19T17:32:08 MatthiasW3) Ist es sogar erheblich komplizierter als ein normaler Array.
2010-01-19T17:32:08 MatthiasW4) Gibt (grep {1} ...) alles zurück, weil 1 immer wahr ist.
2010-01-19T17:32:08 MatthiasWNachdem edit:
Gelten die Punkte 1 und 4 immer noch. Wenn ich den edit richtig verstanden habe, dann bekommst du übrigens genau die Struktur, die ich in meinem Code-Schnipsel verwendet habe. (Also keine weitere Ebene?)
2010-01-19T17:32:08 MatthiasWZum zweiten Edit:
Wozu braucht man denn nun die zweite Ebene, wenn dort Schlüssel und Werte sowieso identisch sind?
2010-01-19T17:42:35 bianca2010-01-19T17:32:08 MatthiasW4) Gibt (grep {1} ...) alles zurück, weil 1 immer wahr ist.
Ja, das will ich an der Stelle, wobei es inzwischen schon rausgeflogen ist, weil überflüssig bei umgedrehter Reihenfolge.
QuoteHat das einen Hasenfuß?
2010-01-19T17:53:45 pqIch würde behaupten,
CODE1 grep {1} CODE2 kann man immer auf CODE1 CODE2 zurückführen. grep {1} ist eine no-op sozusagen. Ausser dass sie überflüssigerweise Zeit verbraucht.
2010-01-19T17:53:45 pqdie komplexität. ich würde lieber den zusätzlichen speicher verbrauchen und einen algorithmus in O(n) behalten. Das sort macht dir das kaputt.
2010-01-19T17:58:23 biancaWelchen Speicher meinst Du hier?
QuoteZweimal Array plus einmal Hash?
Wie sähe damit eine fertige Lösung aus?
2010-01-19T18:08:20 pq
2010-01-19T17:11:19 biancaCode (perl): (dl )1 2 3 4 5 6 7 8 9 10 11 12 13 14 15%hash = ( 1 => { a => '1', }, 2 => { b => '2', }, 3 => { c => '3', }, 4 => { d => '4', }, ); for my $key (sort {$a <=> $b} keys %hash) { print (grep {1} keys %{$hash{$key}}) }
1 2 3 4 5 6 7 8 9 10
my @foo = ( { a => '1', }, { b => '2', }, { c => '3', }, { d => '4', }, ); for my $hash ( @foo ) { print keys %$hash; print "\n"; }
2010-01-18T22:47:25 pq2010-01-18T22:29:30 Escapeam einfachsten wäre wohl ein Hash-Splice (um Doppler zu filtern) aber ich habe die Befürchtung dass ich damit zuviel Speicher belege.
ob du zuviel speicher belegst, kannst du nur selbst beantworten, da nur du die anzahl der keys kennst und wie lang die keys sind. wenn du es genau wissen willst, probier es aus und benutz Devel::Size.
bei der programmierung geht es sehr oft um geschwindigkeit gegenüber speicherverbrauch.
durch die komplexität deines bisherigen algorithmus (jedes element mit jedem vergleichen, also O(n^2) verbrauchst du eine menge zeit. würdest du einen der arrays in einem hash ablegen, um im anderen duplikate zu löschen, würdest du, ich sag jetzt einfach mal, 3 mal soviel speicher verbrauchen, aber ein vielfaches an zeit sparen.
2010-01-18T16:25:40 reneeDu veränderst @new_data, während Du darüber iterierst - gefährlich! Ich vermute, dass Du damit eine quasi-Endlosschleife produzierst und dann schlägt der Timeout zu.