Algorithmus für Listenvergleiche ?
Hallo und Guten Tag !
Ich steh vor einem kleinen Programm/Problem.
Und zwar möchte ich zwei ellenlange Listen miteinander vergleichen, allerdings fällt mir kein effektiverer Algorithmus dafür ein.
Die beiden Listen sehen so aus:
Die Listen haben zwar noch mehr Spalten, aber die sind nicht relevant, die ID ist einzigartig und kommt in jeder der beiden Listen 0-1 Mal vor und nach dem TIMESTAMP will ich vergleichen. Ich möchte letztendlich die aktuellsten Daten zu jeder ID bestimmen.
Bisher mache ich das folgendermaßen:
Das funktioniert auch, aber das simple Durchprobieren aller Kombinationen ist ein wenig "barbarisch" und in meinem Fall leider auch zu ineffizient, da beide Listen gut und gerne zwischen 1000 und 3000 Eintragungen haben.
Kennt ihr zufällig eine Möglichkeit, wie man das noch effizienter gestalten kann ?
Ich steh vor einem kleinen Programm/Problem.
Und zwar möchte ich zwei ellenlange Listen miteinander vergleichen, allerdings fällt mir kein effektiverer Algorithmus dafür ein.
Die beiden Listen sehen so aus:
ID TIMESTAMP
1 2010-01-01_13:30:00
2 2010-01-22_11:00:00
3 2010-01-13_08:20:00
Die Listen haben zwar noch mehr Spalten, aber die sind nicht relevant, die ID ist einzigartig und kommt in jeder der beiden Listen 0-1 Mal vor und nach dem TIMESTAMP will ich vergleichen. Ich möchte letztendlich die aktuellsten Daten zu jeder ID bestimmen.
Bisher mache ich das folgendermaßen:
Liste A, B #Die beiden Listen
#Iteration Liste A
for i=0 to A.count-1
#Iteration Liste B
for j=0 to B.count-1
#Ist A[i] aktueller als B[j] ?
if A[i].TIMESTAMP > B[j].TIMESTAMP then
print A[i]
else
print B[j]
end
end
end
Das funktioniert auch, aber das simple Durchprobieren aller Kombinationen ist ein wenig "barbarisch" und in meinem Fall leider auch zu ineffizient, da beide Listen gut und gerne zwischen 1000 und 3000 Eintragungen haben.
Kennt ihr zufällig eine Möglichkeit, wie man das noch effizienter gestalten kann ?
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 141654
Url: https://administrator.de/contentid/141654
Ausgedruckt am: 22.11.2024 um 21:11 Uhr
7 Kommentare
Neuester Kommentar
Mon,moin.
Haben beide Listen immer die gleichen IDs?
Dann brauchst du nur eine Zählschleife - wenn nicht kann dein Beispiel nicht funktonieren du vergleichst die IDs ja garnicht.
Gruß
LotPings
Haben beide Listen immer die gleichen IDs?
Dann brauchst du nur eine Zählschleife - wenn nicht kann dein Beispiel nicht funktonieren du vergleichst die IDs ja garnicht.
- Deine Datum hat doch günstigerweise schon eine sortierfähige Formatierung, hänge beide Listen aneinander, sortiere sie und behalte immer nur den neuesten Eintrag jeder ID.
- Die Alternative wäre, beide Listen parallel durchzugehen und den bei gleicher ID neueren Eintrag auszugeben; das erhöhen der Zähler bei nicht vorhander ID wird etwas tricky.
Gruß
LotPings
Gut wenn du eine bessere Lösung gefunden hast,
wenn ListeB aufsteigend nach ID sortiert ist, musst du die eigentlich auch nicht immer komplett durchlaufen, wenn du dir den letzten Index merkst, brauchst du nur da aufsetzen, aber natürlich keine foreach Schleife dann.
Gruß
LotPings
wenn ListeB aufsteigend nach ID sortiert ist, musst du die eigentlich auch nicht immer komplett durchlaufen, wenn du dir den letzten Index merkst, brauchst du nur da aufsetzen, aber natürlich keine foreach Schleife dann.
Gruß
LotPings
Moin,
als erstes würde ich empfehlen immer auf die ID zuerst zu vergleichen. Da das ein reiner Zahlenwert ist bedeutet dass das du einen Integer-Vergleich machst. Dies geht um ein vielfaches Schneller als ein komplexer String-Vergleich (im Endeffekt mit einem Maschinenbefehl - cjne u.ä.)
Dann ist die Frage: möchtest du schnell (und speicherintensiv) arbeiten? Falls das ok wäre würde ich das so machen das ich beide Listen vergleiche -> und immer wenn ich eine ID in beiden Listen finde dann wird diese ID in nem Array gepackt.
Danach gehe ich erst durch und sage das ich für jede ID die im Array ist die Datumswerte vergleiche... Das kostet zwar Speicher aber sorgt dafür das ich nur die Werte vergleiche die mich wirklich intressieren (intressant dabei wäre noch ob es eher viele Treffer sein werden - oder nur wenige Treffer zu erwarten sind... Im letzten Fall kann man auch gleich die Datumswerte in den Speicher packen -> dann brauch ich die Liste nicht erst mehrfach von der Platte lesen...)
als erstes würde ich empfehlen immer auf die ID zuerst zu vergleichen. Da das ein reiner Zahlenwert ist bedeutet dass das du einen Integer-Vergleich machst. Dies geht um ein vielfaches Schneller als ein komplexer String-Vergleich (im Endeffekt mit einem Maschinenbefehl - cjne u.ä.)
Dann ist die Frage: möchtest du schnell (und speicherintensiv) arbeiten? Falls das ok wäre würde ich das so machen das ich beide Listen vergleiche -> und immer wenn ich eine ID in beiden Listen finde dann wird diese ID in nem Array gepackt.
Danach gehe ich erst durch und sage das ich für jede ID die im Array ist die Datumswerte vergleiche... Das kostet zwar Speicher aber sorgt dafür das ich nur die Werte vergleiche die mich wirklich intressieren (intressant dabei wäre noch ob es eher viele Treffer sein werden - oder nur wenige Treffer zu erwarten sind... Im letzten Fall kann man auch gleich die Datumswerte in den Speicher packen -> dann brauch ich die Liste nicht erst mehrfach von der Platte lesen...)
Naja - ob du jetzt ne normale ID hast oder ne Gestell-ID -> das bleibt sich gleich... Das Problem für dich fängt an wenn du versuchst 2 Strings (und nen Timestamp ist erstmal nichts anderes) zu vergleichen. Du kannst den jetzt entweder in nen Unix-Timestamp umwandeln - das kostet Zeit... Oder du vergleichst 2 Strings -> das Kostet auch Zeit.
Ist eigentlich auch ganz einfach: Im Maschinencode kannst du entweder (vereinfacht) sagen:
cje (R0,2,xyz)
-> Vergleiche den Wert in Register Null mit ner 2 -> wenn R0 auch eine Zwei enthält springe. Machst du das ganze jetzt mit 2 Texten dann muss er sich ja deinen Text erst in ein nutzbares Format (z.B. Hex,...) umwandeln und das dann Zeichen für Zeichen vergleichen. Selbst wenn man davon ausgeht das der Compare-Befehl 2 Takte benötigt dann ist es glaub ich nachvollziehbar das es bei einem Vergleich von mehreren Tausend Werten einen gewaltigen Unterschied machst ob du jetzt 1000x 2 Takte opferst -> oder 1000 * 19 * 2 Takte (19 weil 2009-01-01 10:00:00 genau 19 Zeichen sind). Wenn du jetzt noch davon ausgehst das jede CPU heute mit Pipelines arbeitet und die bei nem Sprung ggf. noch zurückbearbeitet werden müssen usw. -> dann ist dieser Zeitunterschied gigantisch... Das kann den Unterschied zwischen 2 und 20 Minuten machen...
Was du natürlich auch machen kannst: Du wirst ja vermutlich in einer Datenbank arbeiten -> was wäre denn wenn du einfach die DB die Arbeit machen lässt? Du importierst die Daten von Standort 2 einfach bei Standort 1. Dann lässt du dir eine Liste ausgeben:
Select s1.timestamp, s2.timestamp, s1.id, s2.id from Standort1, Standort2 where s1.id=s2.id
Jetzt hast du schonmal EINE Liste bei der die IDs mit Timestamp vorhanden sind die in beiden Listen sind. Das ganze kannst du natürlich noch verfeinern -> und dein Problem verringert sich sofort erheblich...
Ist eigentlich auch ganz einfach: Im Maschinencode kannst du entweder (vereinfacht) sagen:
cje (R0,2,xyz)
-> Vergleiche den Wert in Register Null mit ner 2 -> wenn R0 auch eine Zwei enthält springe. Machst du das ganze jetzt mit 2 Texten dann muss er sich ja deinen Text erst in ein nutzbares Format (z.B. Hex,...) umwandeln und das dann Zeichen für Zeichen vergleichen. Selbst wenn man davon ausgeht das der Compare-Befehl 2 Takte benötigt dann ist es glaub ich nachvollziehbar das es bei einem Vergleich von mehreren Tausend Werten einen gewaltigen Unterschied machst ob du jetzt 1000x 2 Takte opferst -> oder 1000 * 19 * 2 Takte (19 weil 2009-01-01 10:00:00 genau 19 Zeichen sind). Wenn du jetzt noch davon ausgehst das jede CPU heute mit Pipelines arbeitet und die bei nem Sprung ggf. noch zurückbearbeitet werden müssen usw. -> dann ist dieser Zeitunterschied gigantisch... Das kann den Unterschied zwischen 2 und 20 Minuten machen...
Was du natürlich auch machen kannst: Du wirst ja vermutlich in einer Datenbank arbeiten -> was wäre denn wenn du einfach die DB die Arbeit machen lässt? Du importierst die Daten von Standort 2 einfach bei Standort 1. Dann lässt du dir eine Liste ausgeben:
Select s1.timestamp, s2.timestamp, s1.id, s2.id from Standort1, Standort2 where s1.id=s2.id
Jetzt hast du schonmal EINE Liste bei der die IDs mit Timestamp vorhanden sind die in beiden Listen sind. Das ganze kannst du natürlich noch verfeinern -> und dein Problem verringert sich sofort erheblich...