Array Elemente duplizieren --> Rekursiv

  • Hallo zusammen,

    ich zerbrech mir gerade darüber den Kopf, wie ich die folgende Aufgabe am attraktivsten lösen kann und komm einfach nicht drauf:
    Vielleicht kann irgendjemand meinem Hirn ja einen kleinen Kick in die richtige Richtung verpassen ;)

    Ich hab einen Mehrdimensionalen Array in dem eine Art Baumstruktur abgebildet ist.
    Jede Zeile des Arrays, also jeder "Zweig" des Baumes, hat in einer Spalte eine Stufenangabe und einer anderen eine Mengenangabe drin.
    Nun soll der gesamte Array durchlaufen werden und die "Zweige" entsprechend der Mengenangabe dupliziert werden, jedoch die Struktur des Baums natürlich erhalten bleiben.

    Beispiel:

    Aus dem folgenden Array...

    Stufe Text Menge
    .1 Test 2
    ..2 Test 2
    ...3 Test 2
    ..2 Test 1
    ...3 Test 3

    soll der nachfolgende werden (gerne auch durch Erzeugen eines neuen Arrays in den entsprechend rüberkopiert wird).

    Stufe Text Menge
    .1 Test 2
    ..2 Test 2
    ...3 Test 2
    ...3 Test 2
    ..2 Test 2
    ...3 Test 2
    ...3 Test 2
    ..2 Test 1
    ...3 Test 3
    ...3 Test 3
    ...3 Test 3
    .1 Test 2
    ..2 Test 2
    ...3 Test 2
    ...3 Test 2
    ..2 Test 2
    ...3 Test 2
    ...3 Test 2
    ..2 Test 1
    ...3 Test 3
    ...3 Test 3
    ...3 Test 3

    Die Spalte Menge kann gerne auch ganz wegfallen, da diese Info ja dann nicht mehr benötigt wird.

    Ich komm einfach nicht drauf bzw. denk vielleicht auch zu kompliziert in vielen verschachtelten For Schleifen...

    Hat irgendjemand einen Tip? Gibts vielleicht schon irgendwo im Forum einen Ansatz?

    Bin für jede Hilfe dankbar.

    Viele Grüße

    Daniel

    P.S.: Wie kann man eigentlich in einem Post eine Art Tabelle aufbauen?

    Einmal editiert, zuletzt von basementmedia (25. Juli 2013 um 15:52)

  • Also prinzipiell sollte das so schwer nicht sein, aber ich verstehe denke ich das System nicht ganz und bin mir auch nicht sicher ob es wirklich sinnvoll ist die Daten so zu strukturieren wie du das vor hast. Beim speichern von Daten sollte man immer zwei Dinge bedenken, zum einen sollte man Redundanz vermeiden, was schonmal für die ursprüngliche Speicherung spricht, zum anderen sollten die Daten so strukturiert sein, dass man sie leicht und schnell auslesen kann. Ich vermute du willst eine Art Organigramm oder eine Stückliste speichern, daher würde ich ein 2D Array nach diesem Schema verwenden:

    Code
    Name/Stufe	1	2	3	4	5	...
    Schraube	3	4	3	0	0	...
    Blech		1	3	0	4	0	...
    BlaBla		0	0	0	1	2	...

    Aber vielleicht hab ich das auch falsch verstanden, was bei "Test" eben auch schwer nachvollziehbar ist. Vielleicht magst du nochmal genauer erklären woher die Daten stammen, wie sie aussehen wenn du sie bekommst, was du damit machen willst und warum du unbedingt diese Speicherstruktur haben möchtest.

    Mehrdimensional ist im übrigen eine ziemlich unklare Aussage. Ist es nun ein 2D oder ein 3D Array?

  • Hi,

    das mit der Redundanz hat in diesem Fall einen Grund.
    Das Progrämmchen, dass ich gerade schreibe dient zur Aufbereitung einer CSV-Datei, die aus dem SAP kommt (Extrakt einer Stückliste).
    Das was alles mit "Test" bezeichnet sind, sind verschiedene Baugruppen und Bauteile, die eben in einer bestimmten Menge verbaut sind.
    Nun kann jedes dieser Teile eine andere Nummer haben, die darauf graviert ist aber eben nicht in der StüLi erfasst ist sondern manuell eingetragen werden muss.

    Damit man zu jedem Bauteil separat diese Nummer erfassen kann, muss die Liste auf die von mir beschriebene Weise aufgefächert werden, sodass man eben z.B. anstatt einer Zeile mit der Mengenangabe "2" zwei einzelne Zeilen hat um anschließend jeweils die Nummer eintragen zu können.

    gibt es keine einfache Lösung, um genau die beschriebene Umwandlung des Arrays zu machen (bzw. einen neuen Array zu schreiben, der genau so aufgebaut ist)?

    Danke und viele Grüße

    Daniel

  • misterspeed
    Der Threadsteller möchte gerne sein Array nach einem bestimmten Verfahren duplizieren. Dafür hat er folgendes Array angelegt:

    Spoiler anzeigen


    Dabei steht der erste Index für die Stufe (0), den Text (1) oder der Menge (2). Der zweite Index steht dabei für den entsprechenden Inhalt. So kommen wir auf folgende Tabelle:

    Spoiler anzeigen
    Code
    Stufe | Text | Menge
    --------------------
      1   | Test |   2
      2   | Test |   2
      3   | Test |   2
      2   | Test |   1
      3   | Test |   3

    Nun sollen Anhand dieser Informationen, ein neue Tabelle (Array) erstellt werden. Dabei wird Zeile für Zeile eingelesen. Das erste Element [0][0] beinhaltet ja die Stufe "1". Dies ist ein äußeres Element für eine später Baumstruktur. Das nächste Element [1][0] enthält den Text. Dieser muss in dem Array zugewiesen werden. Das letzte Element [2][0] enthält die Menge. Es soll also in dem neuen Array diese Zeile aus der Tabelle genau 2x hinein geschrieben werden:

    Spoiler anzeigen
    Code
    Stufe | Text
    ------------
    ! 1   | Test
    ! 1   | Test

    Nun folgt das nächste Element des alten Arrays: "2 | Test | 2". Die Stufe beträgt "2", der Text "Test" und die Menge auch "2". Das bedeutet, dass dieses Element unter JEDES Element der Stufe "1" dupliziert werden soll. Unsere Tabelle nimmt folgende Form an:

    Spoiler anzeigen
    Code
    Stufe | Text
    ------------
      1   | Test
    !  2  |  Test
    !  2  |  Test
      1   | Test
    !  2  |  Test
    !  2  |  Test

    Nun folgt folgender Eintrag: "3 | Test | 2". Hier hat das Element die Stufe "3", den Text "Test" und die Menge "2". Unter JEDES Element der Stufe 2 soll nun 2 mal dieses Element geschrieben werden:

    Spoiler anzeigen

    Nun folgt der nächste Eintrag: "2 | Test | 1". Auch hier wieder unter JEDES Element der Stufe 1 das Element 1x drunter schreiben:

    Spoiler anzeigen

    Zuletzt das letzte Element: "3 | Test | 3". Hier ist aber zu beachten, dass sich dies nur auf das letzte Angelegte Array Element bezieht, welches die Stufe 2 hat:

    Spoiler anzeigen

    Der Threadsteller sucht nun nach einem Anstubser in die Richtige Richtung, um genau dieses Verfahren zu programmieren. Um also aus dem alten Array das hier gezeigte neue Array zu erstellen. Ich hoffe ich konnte helfen das Problem des Threadstellers besser zu verstehen.

    Ich selber setze mich jetzt auch an einen Code ran.
    LG. Make :)

  • Hi,

    danke für deine ausführliche Version meiner Problembeschreibung ;)
    Leider fehlt es mir etwas an der Programmierpraxis, um das von dir in Reinschrift verfasste in Code umzuschreiben.
    Eine Frage wäre: Gibt es bei Autoit einen Befehl, um innerhalb eines Arrays Elemente dazwischen zu speichern und alle weiteren automatisch entsprechend zu verschieben? denn so einen Befehl bräuchte ich ja, um beispielsweise die Zeile mit der Stufe 3 zweimal unterhalb das Array Element der stufe 2 zu schreiben.

    Das heist ich müsste erstmal im Ergebnisarray das Element mit der Stufe 2 finden (wobei es ja mehrere mit der Stufe 2 gibt und ich das richtige "erwischen" muss.
    dies solte sich mit ArrayFindAll lösen lassen. Aber wenn ich die Positionen im Ergebnisarray gefunden habe: Wie kann ich nun die erforderliche Menge an Zeilen zwischen rein "schieben" ohne andere Array Elemente zu überschreiben?

    Viele Grüße

    Daniel

  • Du reservierst dir erst einmal Platz dadrin indem du das Array einmal an der entsprechenden Position aufteilst, dann das erste Array (des aufgeteilten Arrays) mit ReDim um deine Menge erweiterst und dann das andere Array wieder einfügst. So in etwa,...

    Oder du verwendest die Funktion _ArrayInsert() aus der Array.au3.

    LG. Make :)

  • Damit man zu jedem Bauteil separat diese Nummer erfassen kann, muss die Liste auf die von mir beschriebene Weise aufgefächert werden, sodass man eben z.B. anstatt einer Zeile mit der Mengenangabe "2" zwei einzelne Zeilen hat um anschließend jeweils die Nummer eintragen zu können.


    Aber ist das nicht eher die Beschreibung einer dritten Dimension? Nehmen wir nochmal meine Tabelle:


    Code
    Name/Stufe	1	2	3	4	5	...
    Schraube	3	4	3	0	0	...
    Blech		1	3	0	4	0	...
    BlaBla		0	0	0	1	2	...


    Du kannst hier schonmal speichern, welche stufe wieviele Bauteile enthält. Wenn wir das nun in einem Würfel, also in einem 3D Array darstellen kannst du für jedes Bauteil jeder Stufe auch noch einen zusätzlichen Wert (deine Nummer/Gravur) speichern. Da ich das hier grafisch nicht wirklich darstellen kann versuche ich das mal in code auszudrücken:

    [autoit]


    Dim $aData[3][3][4] ; Aufbau: Dimension 1 sind die Namen/Bezeichnung der Bauteile, Dimension 2 sind die Stufen, Dimension 3 bietet Platz für die Gravur, die Anzahl der eingetragenen Gravuren entspricht der Anzahl der vorhandenen Bauteile einer Gruppe, das Array ist 1 basiert, index 0 wird jeweils zur Erläuterung der Datensätze oder der Angaben der Mengen verwendet

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $aData[0][0][0]="*" ; die äussere Ecke des Würfels
    $aData[1][0][0]="Schraube"
    $aData[2][0][0]="Blech"

    [/autoit][autoit][/autoit][autoit]

    $aData[1][1][0]="Menge der Schrauben für Stufe 1"
    $aData[1][2][0]="Menge der Schrauben für Stufe 2"

    [/autoit][autoit][/autoit][autoit]

    $aData[2][1][0]="Menge der Bleche für Stufe 1"
    $aData[2][2][0]="Menge der Bleche für Stufe 2"

    [/autoit][autoit][/autoit][autoit]

    $aData[1][1][1]="Gravur der Schraube 1 von Stufe 1"
    $aData[1][1][2]="Gravur der Schraube 2 von Stufe 1"
    $aData[1][1][3]="Gravur der Schraube 3 von Stufe 1"

    [/autoit][autoit][/autoit][autoit]

    $aData[1][2][1]="Gravur der Schraube 1 von Stufe 2"
    $aData[1][2][2]="Gravur der Schraube 2 von Stufe 2"
    $aData[1][2][3]="Gravur der Schraube 3 von Stufe 2"

    [/autoit][autoit][/autoit][autoit]

    $aData[2][1][1]="Gravur des Blechs 1 von Stufe 1"
    $aData[2][1][2]="Gravur des Blechs 2 von Stufe 1"
    $aData[2][1][3]="Gravur des Blechs 3 von Stufe 1"

    [/autoit][autoit][/autoit][autoit]

    $aData[2][2][1]="Gravur des Blechs 1 von Stufe 2"
    $aData[2][2][2]="Gravur des Blechs 2 von Stufe 2"
    $aData[2][2][3]="Gravur des Blechs 3 von Stufe 2"

    [/autoit]

    Einmal editiert, zuletzt von misterspeed (25. Juli 2013 um 00:07)

  • Hey basementmedia,
    ich habe dir hier ein Skript geschrieben, welches (fast) deine Anforderung erfüllt.
    Der Einzige Fehler der da noch enthalten ist, dass sich die neuen Elemente direkt unter dem letzten erstellten Element der höheren Stufe drunter schieben. Aus diesem Grund wird auch dein 3er Packet der Elemente der Stufe 3 direkt unter den Elementen der Stufe 2 geschrieben. Kurz gesagt, so:

    Spoiler anzeigen

    Hier das Skript:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $sList, $avArr

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $sList = '1|Test|2' & @CRLF & _
    '2|Test|2' & @CRLF & _
    '3|Test|2' & @CRLF & _
    '2|Test|1' & @CRLF & _
    '3|Test|3'

    [/autoit] [autoit][/autoit] [autoit]

    ;~ $sList = '1|A|3' & @CRLF & _
    ;~ '2|B|2' & @CRLF & _
    ;~ '2|C|1'

    [/autoit] [autoit][/autoit] [autoit]

    $avArr = _ListToArray($sList)
    $avArr = _ArrayUnfold($avArr)
    _ArrayDisplay($avArr)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _ListToArray($sList)
    Local $avArr = StringSplit($sList, @CRLF, 1)
    Local $avRet[$avArr[0]][3], $i, $avTemp
    Local Enum $_Stufe, $_Text, $_Menge

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To $avArr[0]
    $avTemp = StringSplit($avArr[$i], '|', 2)
    $avRet[$i -1][$_Stufe] = $avTemp[$_Stufe]
    $avRet[$i -1][$_Text] = $avTemp[$_Text]
    $avRet[$i -1][$_Menge] = $avTemp[$_Menge]
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $avRet
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _ArrayUnfold($avArr)
    Local $avRet[$avArr[0][2]][2], $i, $n, $in
    Local Enum $_Stufe, $_Text, $_Menge

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($avRet) -1
    $avRet[$i][$_Stufe] = '>' & $avArr[0][$_Stufe]
    $avRet[$i][$_Text] = $avArr[0][$_Text]
    Next
    ;~ _ArrayDisplay($avRet)

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To UBound($avArr) -1
    $n = 0
    While $n < UBound($avRet)
    If '>' & $avArr[$i][$_Stufe] == $avRet[$n][$_Stufe] Then $avRet[$n][$_Stufe] = StringTrimLeft($avRet[$n][$_Stufe], 1)

    [/autoit] [autoit][/autoit] [autoit]

    If '>' & $avArr[$i][$_Stufe] -1 == $avRet[$n][$_Stufe] Then
    _ArrayReserve($avRet, $avArr[$i][$_Menge], $n)
    For $in = $n +1 To $n + $avArr[$i][$_Menge]
    $avRet[$in][$_Stufe] = '>' & $avArr[$i][$_Stufe]
    $avRet[$in][$_Text] = $avArr[$i][$_Text]
    Next
    $n += $avArr[$i][$_Menge]
    ;~ _ArrayDisplay($avRet)
    EndIf
    $n += 1
    WEnd
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($avRet) -1
    If StringLeft($avRet[$i][$_Stufe], 1) == '>' Then $avRet[$i][$_Stufe] = StringTrimLeft($avRet[$i][$_Stufe], 1)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $avRet
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _ArrayReserve(ByRef $avArr, $iReserve, $iIndex)
    Local $iSize = UBound($avArr) + $iReserve
    Local $iDim = UBound($avArr, 2)
    Local $avTemp = $avArr
    Local $i, $n

    [/autoit] [autoit][/autoit] [autoit]

    ReDim $avArr[$iSize][$iDim]

    [/autoit] [autoit][/autoit] [autoit]

    For $i = $iIndex +1 To $iIndex + $iReserve
    For $n = 0 To $iDim -1
    $avArr[$i][$n] = 0
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $i = $iIndex +1 + $iReserve To $iSize -1
    For $n = 0 To $iDim -1
    $avArr[$i][$n] = $avTemp[$i - $iReserve][$n]
    Next
    Next
    EndFunc

    [/autoit]

    Du musst da noch zwischen Zeile 58 und 59 ein Codestück einfügen, der alle vorherigen Elemente übersprint um somit das neue Element auch tatsächlich hinten einzufügen. Ich selber komme aber auch nicht drauf wie man das am besten macht. Ich hoffe ich konnte weiterhelfen!

    LG. Make :)

  • Hi Make Grafik,

    1000 Dank für deine Hilfe. :rock:
    Ich stürz mich gleich mal drauf!
    Ich schick dir einen Kasten Bier, ok ? ;)


    Beste Grüße

    Daniel