2D Array - Doppelte Beziehungen bestimmter Spalten in einem Array ermitteln und löschen

  • Hallo zusammen,

    ich hoffe ihr könnt mir weiterhelfen.

    Aus einem Excel ähnlichen Format erstelle ich mir ein 2D Array.

    In diesem 2D Array würde ich gerne doppelte Einträge löschen, allerdings nicht einfach wenn ein Wert doppelt vorkommt, sondern vielmehr wenn eine Beziehung einer Zeile zwischen bsp. zwei Spalten mehrfach im gesamten 2D Array vorkommt.

    Ich habe jetzt schon vieles probiert, "_ArrayUnique", oder mein Array durchschleifen und dabei einzelne Spalten gesondert speichern und pro Durchgang prüfen ob Beide vorhanden sind, aber irgendwie bekomme ich die Programmlogik für eine Beziehung der Spalten nicht sauber hin.

    Darum wollte ich euch bitten, mir bei diesem Problem zu helfen.

    Um mal zu zeigen in welchem Format mein Array besteht, habe ich folgendes beispiel:

    Haus A Haustür A Straße Haus B Haustür B
    abc 1
    333
    def
    1
    def 1 333 abc 1
    def 2 444 abc 2
    abc 3 555 ghi 1
    jkl 1 333 xyz 3
    ghi 1 555 abc 3

    Die rot gefärbten Zeilen 2 und 6 wären in diesem Fall doppelte Beziehungen, die ich gerne jeweils rauslöschen würde.

    Die Beziehung selbst soll zws. "Haus A" und "Haus B" bestehen, aber es muss auch drauf geachtet werden, falls "Haus A" = "Haus B" doppelt ist, das die verschiedenen Straßen beachtet werden, welche einzigartig pro gleicher Beziehung zws Haus A und Haus B sind (Beispiel Zeile 1, 2 und 3 - während Zeile 2 eine doppelte Beziehung zu Zeile 1 ist, ist Zeile 3 eine neue Beziehung, wegen einer anderen Straße). Straßen hingegen können doppelt vorkommen, solange sie nicht innerhalb der gleichen Beziehung zws. Haus A und Haus B ist.

    Bei allem kann ein Wert aus Haus A öfters, oder sogar unter der Spalte Haus B vorkommen, die Bezeichnung eines Hauses ist aber einzigartig.

    Großes Problem und ich zerbreche mir hier sehr den Kopf.

    Hätte jemand Ideen für und kann mir bitte weiterhelfen?

    Vielen Dank schon mal.

    Grüße

    borsTiHD

  • Zitat

    Aus einem Excel ähnlichen Format erstelle ich mir ein 2D Array.

    Nicht zufällig aus einer SQL Datenbank, hmn? ^^

    Nur eine Vermutung... :P

    Wenn das der Fall ist, kannst du nämlich mit der richtigen SQL Abfrage die doppelten Daten nämlich vorab aussortieren. Das würde dein Problem komplett beseitigen und wir reden hier nicht um den heißen Brei herum...

    Ansonsten erläutere doch erst mal von WO die Daten her kommen, um WELCHE Daten es sich handelt und WIE du diese einlest. Vielleicht lässt sich schon da was machen mit Strukturänderungen, um die Problemlösung zu vereinfachen. Denn was du da beschreibst von dem Problem her, könnte je nach Menge der Daten einiges an unnötiger Zeit kosten. Bevor ich dir also da mehrere Lösungswege gebe, wäre es gut wenn du mal ein paar Hintergrundinformationen liefern würdest. Du kannst es aber auch lassen, dann sag aber bescheid dass du nicht mehr Informationen preis geben willst. Dann werde ich eben auf dein geschildertes Beispiel einige Lösungsansätze vorschlagen.

    Aber ich wette die passen dann zu 85% nicht zu deinem eigentlichen Problem. Erfahrungsgemäß...

    ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    Okey, ansonsten hier mal ein Lösungsansatz bezogen auf dein Beispiel:

    Zuerst einmal brauchen wir eine Funktion welche 2 Datensätze miteinander vergleicht und überprüft, ob es sich um die selbe Beziehung (wie du sie geschildert hast) handelt:

    Da wir nun eine Funktion haben welche die Dateneinträge vergleichen kann, können wir eigentlich das ganze Array einfach durchlaufen und die doppelten Einträge so ausfindig machen:

    Und ab dieser Stelle aus musst du eigentlich nur noch dein Array kopieren und die gefundenen Einträge überspringen:

    5 Mal editiert, zuletzt von Yjuq (22. April 2018 um 00:52)

  • Morgen, bin grad erst aufgestanden. :)

    Vielen vielen Dank erstmal für den Lösungsansatz.

    Hab den mir grad im halbschlaf durchgelesen und werde das mal versuchen umzusetzen. :D

    Die Daten selbst bekomme ich leider nicht aus einer Datenbank, sondern vielmehr aus einer Eventliste, in der ich lediglich die Zeilen markieren und kopieren kann.

    Wenn man eine solche Zeile eines Events kopiert, erhält man zudem die Spalten Namen in die ersten Zeile.

    Was sich dann im Clipboard befindet lese ich mit "$aClipBoard = _StringSplit2D($sString)" in ein Array.


    Deswegen kann ich das Problem leider nicht umgehen um es in dem jeweiligen Ursprungsort vorher zu filtern. :(

    Und ich denke man kann es erkennen, es sind Beziehungen zws. Netzelementen, aber da kann ich leider nicht mehr zu sagen.


    //€dit:

    Habs gerade mal umgesetzt und auf dem ersten Blick und in einem kleinen Test scheint es perfekt so zu klappen. :D

    Ich muss mir da aber noch paar ConsoleWrites einbauen, damit ich in Zukunft es schneller nachvollziehen kann.

    Aber verstehe ich die Logik richtig, dass du alle Beziehungen checkst... Immer von Zeile 1 mit den restlichen, danach Zeile 2 mit den restlichen (also quasi immer nach unten).

    Wenn eine Zeile davon doppelt erkannt wird, wird die gerade zu prüfende Zeile als true makiert und egal ob die anderen Zeilen nicht doppelt (false) sind, der $check bleibt für diese eine zu prüfende Zeile immer true (wegen $check = true Or false).

    Sobald alle Zeilen geprüft wurden (sagen wir mal für Zeile 1), und mindestens eine Beziehung gefunden wurde (also $check = true), dann wird die Zeile einfach übersprungen.

    Irgendwann befindet sich die Schleife an dem Punkt wo die "letzte doppelte" Beziehung für Zeile 1 gefunden wurde (zb. Zeile 9). Dort bleibt $check = false und nur dann wird die Zeile in das neue Array geschrieben.

    Also hab ich quasi immer die letzte Zeile aller doppelten Beziehungen im Array?

    Hab ich das so richtig nachvollziehen können? :)

    Ich werde das die Tage mal ausführlicher testen und danke dir tausendfach dafür. :D

    Einmal editiert, zuletzt von borsTiHD (22. April 2018 um 09:00)

  • Mir ist gerade aufgefallen, dass ich noch'n kleinen Bug drin hab. Folgende Daten werden ebenfalls als doppelte Einträge erkannt:

    Haus A Haustür A Straße Haus B Haustür B
    aaa 1 222 xyz 2
    aaa 1 222 def 1

    Meine Abfrage in der quickCheckRelaion() behandelt dieses Fallbeispiel nicht, wenn Einträge (Haus, Haustür und Straße) zwar zu 100% übereinstimmen, aber die Relation zwischen den anderen Daten unterschiedlich ist.

    Zitat

    Aber verstehe ich die Logik richtig, dass du alle Beziehungen checkst... Immer von Zeile 1 mit den restlichen, danach Zeile 2 mit den restlichen (also quasi immer nach unten).

    Wenn eine Zeile davon doppelt erkannt wird, wird die gerade zu prüfende Zeile als true makiert und egal ob die anderen Zeilen nicht doppelt (false) sind, der $check bleibt für diese eine zu prüfende Zeile immer true (wegen $check = true Or false).

    Sobald alle Zeilen geprüft wurden (sagen wir mal für Zeile 1), und mindestens eine Beziehung gefunden wurde (also $check = true), dann wird die Zeile einfach übersprungen.

    Ja, das hast du richtig verstanden. Damit überprüfe ich das erste Element und alle danach folgenden und prüfe einfach, ob sich solch eine Relation nochmal im Array vorkommt. Ist das der Fall kann die Relation an der Stelle übersprungen werden, da ja die gleiche nochmal vorkommt und die ebenfalls mit den nachfolgenden Elementen noch mal geprüft wird.

    Zitat

    Irgendwann befindet sich die Schleife an dem Punkt wo die "letzte doppelte" Beziehung für Zeile 1 gefunden wurde (zb. Zeile 9). Dort bleibt $check = false und nur dann wird die Zeile in das neue Array geschrieben.

    Also hab ich quasi immer die letzte Zeile aller doppelten Beziehungen im Array?

    Korrekt, der Grund dahinter ist um die nötigen Schleifendurchläufe zu reduzieren. Eigentlich kann man sogar schon die Suche dann komplett beenden für die Stelle, sobald ein doppelter Eintrag gefunden wurde. Sieht dann so aus:

    AutoIt
        For $b = $a +1 To UBound($data, 1) -1 ; Zeile 18 im Orginalskript
            $check = $check Or quickCheckRelation($data, $a, $b)
            If $check Then ExitLoop
        Next

    Wozu sollten dann auch noch die anderen Elemente geprüft werden wenn sowieso schon fest steht, dass der Eintrag dann übersprungen wird? Beschleunigt das Ganze bei größeren Datenmengen etwas.

    ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    Hier der Fix zu dem oberen beschriebenen Bug:

    Zudem habe ich auch die Abfrage optimiert und die Bedingungen von vielen OR auf AND geändert. Das hat den Effekt, wenn eine Bedingung schon nicht zutrifft (also FALSE ist), dass der Rest nicht mehr überprüft wird. Beschleunigt die Abfrage auch um einiges. ^^

    Im besten Fall gibt's nur eine Abfrage (Wenn die Straße unterschiedlich ist) und im schlimmsten Fall 8 (wenn sich alle Daten gleichen bis auf die Haustür und die Relationen von der Position getauscht sind).

    3 Mal editiert, zuletzt von Yjuq (22. April 2018 um 17:34)

  • Mir ist gerade aufgefallen, dass ich noch'n kleinen Bug drin hab. Folgende Daten werden ebenfalls als doppelte Einträge erkannt:

    Haus A Haustür A Straße Haus B Haustür B
    aaa 1 222 xyz 2
    aaa 1 222 def 1

    Meine Abfrage in der quickCheckRelaion() behandelt dieses Fallbeispiel nicht, wenn Einträge (Haus, Haustür und Straße) zwar zu 100% übereinstimmen, aber die Relation zwischen den anderen Daten unterschiedlich ist.

    Das wäre nicht schlimm. Die Haustür eines Hauses ist fest mit einem anderen Haus Verknüpft, es kann aber passieren dass zwei gleiche Häuser über zwei unterschiedliche Strecken verbunden sind.

    Die Straßen können auch doppelt vorkommen, solange es unterschiedliche Häuser sind (haben dann zwar den gleichen Straßenname, aber es ist eine andere Straße).

    Allerdings kann bei dem selben Haus keine Straße doppelt vorkommen. Also ein und dasselbe Haus kann eine Straße nur einmalig belegen.

    Will damit sagen, das Haus "abc" ist einzigartig, kann aber als "Haus A" als auch als "Haus B" vorkommen (kommt immer drauf an, welches Haus den Event gesendet hat, dieses ist dann Haus A),

    Das Haus "abc" kann mehrere Haustüre besitzen.

    Jede Haustür kann nur zu "einem" anderen Haus führen.

    Das Haus "abc" kann aber mit merheren Haustüren unterschiedliche andere Häuser erreichen (aber immer noch pro Haustür nur ein anderes Haus).

    Die einzelnen Straßen von Haus "abc" tragen immer einen anderen Namen.

    Das Beispiel von dir kann daher nicht auftreten, da dort das selbe Haus "aaa" mit der selben Haustür "1" zu unterschiedlichen Häusern käme.

    Den Fall gibt es nicht.

    Ich glaube ich muss die Regeln vlt nochmal irgendwie sammeln und übersichtlicher gestalten, da es ganz schön durcheinander geschrieben wurde von mir (sorry dafür). :/

    Vielen Dank nochmal das du dir so viel Mühe machst. :)

    Das mit dem Exit Loop ist jetzt auch mit drin, das ist einfach aber super. :D