Что нового

Печать многоуровневого массива

DyadyaGenya

Знающий
Сообщения
306
Репутация
10
Доброго времени суток. Возможно где-то и есть такая тема, но не нашел. По сути изначально нужно было печатать/выводить трёхмерный массив. И такие темы есть. И Не то, чтобы оно мне было очень нужно. Свою задачу по печати 3-4 уровневого массива я сделал. Но не получается сделать это универсальным. Пока имею например для 4-х мерного массива такое для вывода в консоль:
Код:
Func printArray4dToConsole($aArray)
    ; Проверяем, является ли массив 4-мерным
    If Not IsArray($aArray) Or UBound($aArray, 0) <> 4 Then
        ConsoleWrite("Ошибка: Переданный массив не является 4-мерным." & @CRLF)
        Return
    EndIf

    ; Начинаем вывод массива
    ConsoleWrite("Array" & @CRLF)
    ConsoleWrite("(" & @CRLF)
    For $i = 0 To UBound($aArray, 1) - 1
        ConsoleWrite("    [" & $i & "] => Array" & @CRLF)
        ConsoleWrite("    (" & @CRLF)
        For $j = 0 To UBound($aArray, 2) - 1
            ConsoleWrite("        [" & $j & "] => Array" & @CRLF)
            ConsoleWrite("        (" & @CRLF)
            For $k = 0 To UBound($aArray, 3) - 1
                ConsoleWrite("            [" & $k & "] => Array" & @CRLF)
                ConsoleWrite("            (" & @CRLF)
                For $l = 0 To UBound($aArray, 4) - 1
                    ConsoleWrite("                [" & $l & "] => " & $aArray[$i][$j][$k][$l] & @CRLF)
                Next
                ConsoleWrite("            )" & @CRLF)
            Next
            ConsoleWrite("        )" & @CRLF)
        Next
        ConsoleWrite("    )" & @CRLF)
    Next
    ConsoleWrite(")" & @CRLF)
EndFunc

Или для печати в файл:
Код:
Func printArray4d($aArray, $sFilePath)
    ; Открываем файл для записи
    Local $hFile = FileOpen($sFilePath, 2) ; 2 = Режим перезаписи файла
    If $hFile = -1 Then
        MsgBox(16, "Ошибка", "Не удалось открыть файл для записи: " & $sFilePath)
        Return
    EndIf

    ; Начинаем запись массива
    FileWriteLine($hFile, "Array")
    FileWriteLine($hFile, "(")
    For $i = 0 To UBound($aArray, 1) - 1
        FileWriteLine($hFile, "    [" & $i & "] => Array")
        FileWriteLine($hFile, "    (")
        For $j = 0 To UBound($aArray, 2) - 1
            FileWriteLine($hFile, "        [" & $j & "] => Array")
            FileWriteLine($hFile, "        (")
            For $k = 0 To UBound($aArray, 3) - 1
                FileWriteLine($hFile, "            [" & $k & "] => Array")
                FileWriteLine($hFile, "            (")
                For $l = 0 To UBound($aArray, 4) - 1
                    FileWriteLine($hFile, "                [" & $l & "] => " & $aArray[$i][$j][$k][$l])
                Next
                FileWriteLine($hFile, "            )")
            Next
            FileWriteLine($hFile, "        )")
        Next
        FileWriteLine($hFile, "    )")
    Next
    FileWriteLine($hFile, ")")

    ; Закрываем файл
    FileClose($hFile)
EndFunc

Ну или так:
Код:
Func Write4DArrayToFile($aArray, $sFilePath, $sDelimiter)
    ; Проверяем, является ли массив четырёхмерным
    If Not IsArray($aArray) Or UBound($aArray, 0) <> 4 Then
        MsgBox(16, "Ошибка", "Переданный массив не является четырёхмерным.")
        Return False
    EndIf

    ; Открываем файл на запись
    Local $hFile = FileOpen($sFilePath, 2)
    If $hFile = -1 Then
        MsgBox(16, "Ошибка", "Не удалось открыть файл для записи.")
        Return False
    EndIf

    ; Проходим по всем уровням массива и записываем в файл
    For $i = 0 To UBound($aArray, 1) - 1
        FileWriteLine($hFile, "Срез уровня 1 [" & $i & "]:")
        For $j = 0 To UBound($aArray, 2) - 1
            FileWriteLine($hFile, "  Срез уровня 2 [" & $j & "]:")
            For $k = 0 To UBound($aArray, 3) - 1
                ; Формируем строку для текущей строки с разделителем
                Local $sLine = ""
                For $l = 0 To UBound($aArray, 4) - 1
                    $sLine &= $aArray[$i][$j][$k][$l] & $sDelimiter
                Next
                ; Убираем последний разделитель и записываем строку
                $sLine = StringTrimRight($sLine, StringLen($sDelimiter))
                FileWriteLine($hFile, "    " & $sLine)
            Next
            FileWriteLine($hFile, "") ; Добавляем пустую строку между подуровнями
        Next
        FileWriteLine($hFile, "") ; Добавляем пустую строку между срезами
    Next

    ; Закрываем файл
    FileClose($hFile)
    Return True
EndFunc
Но хотелось бы универсальности и наглядности для многомерного массива. Ведь если верить справке, то можно создавать до 64 уровней

Я пробовал рекурсию, как я её понимаю, но получается, что нужно обращаться что-то типа $aArray[$i]. А к многомерному массиву так не обратишься.. Будет ошибка.
Пробовал использовать для цикла UBound($aArray, 0), но без особых успехов. Пока вот так:
Код:
Func MultiArray2($Array)

       ; Определяем количество измерений массива
    Local $iDimensions = UBound($aArray, 0)

    ; Создаём массив-каунтер с количеством элементов, равным числу измерений
    Local $aCounter[$iDimensions]

    ; Заполняем массив-каунтер
    For $i = 0 To $iDimensions - 1
        $aCounter[$i] = $i + 1 ; Индексы начинаются с 1 для измерений
    Next

_ArrayDisplay($aCounter)

Local $sSpaces = _StringRepeat(" ", 4)

       ConsoleWrite("Array"  & @CRLF)
    ConsoleWrite("("  & @CRLF)
    ; Начинаем запись массива
     For $i = 0 To UBound($Array, 0)-1
       If UBound($Array, $i) <> 0 Then
         ConsoleWrite("    [" & $i & "] => Array" & @CRLF)
             ConsoleWrite("("  & @CRLF)
         For $j =0 To UBound($aCounter)-1
       ;ConsoleWrite("Количество элементов в измерении " & $i & ": " & UBound($Array, $i) & @CRLF)
            ConsoleWrite($aCounter[$j]  & @CRLF)

         Next
            ConsoleWrite(")"  & @CRLF)
       EndIf

   Next
    ConsoleWrite(")"  & @CRLF)
EndFunc
 
Последнее редактирование:

Alecsis

Осваивающий
Сообщения
125
Репутация
45
Привет + с наступившим НГ! Вот результат эксперимента «на табуретке» :acute:
PS1 Конечно в исходнике бардак, но для 1-D, 2-D и 3-D проверено и работает.
PS2 Постарался хоть как-то откомментить, но сильно не пинайте — чукча не литератор…
 

Вложения

  • MultiArray.7z
    3.3 КБ · Просмотры: 1
Автор
D

DyadyaGenya

Знающий
Сообщения
306
Репутация
10
Привет + с наступившим НГ!
И вас аналогично с наступившим НГ )))
Вот результат эксперимента «на табуретке» :acute:

Самое время для экспериментов ))) Весной/летом/осенью огороды, а сейчас делать нечего )))
Конечно в исходнике бардак
В моих исходниках ещё хуже. Правда сюда стараюсь подчищенные вылаживать.
но для 1-D, 2-D и 3-D проверено и работает.
Проверил, работает и для большего. Но как у вас написано в логах, если не хватает терпения заполнить больший массив, то можно делать как я, правда забыл переделать под любой размер, сделал для 7-ми уровневого цикл заполнения. Он не совсем полный, но для проверки пойдет:
Код:
; Объявляем массив с 7 уровнями
Local $aArray[2][2][2][2][2][2][2]

; Генерация данных с помощью циклов
For $i1 = 0 To 1
    For $i2 = 0 To 1
        For $i3 = 0 To 1
            For $i4 = 0 To 1
                For $i5 = 0 To 1
                    For $i6 = 0 To 1
                        For $i7 = 0 To 1
                            $aArray[$i1][$i2][$i3][$i4][$i5][$i6][$i7] = "Value-" & $i1 & $i2 & $i3 & $i4 & $i5 & $i6 & $i7
                        Next
                    Next
                Next
            Next
        Next
    Next
 Next
Глубоко ваш код не смотрел. Возможно что-то подсмотрю и себе. По полученному результату можно взять и ваш, но так не видна структура.
Я как раз пришел к вот такому варианту:
Код:
Func _printArray(Const ByRef $avArray)
    If Not IsArray($avArray) Then Return SetError(1, 0, '')

    Local $iDimensions = UBound($avArray, 0) ; Определяем количество измерений
    Local $aCounters[$iDimensions] ; Массив-счётчик для индексов
    Local $aBounds[$iDimensions] ; Массив границ для каждого уровня
    Local $aStartedLevels[$iDimensions] = [False] ; Отслеживаем, начат ли уровень

    ; Заполняем границы
    For $i = 0 To $iDimensions - 1
        $aBounds[$i] = UBound($avArray, $i + 1)
        $aCounters[$i] = 0
    Next

    Local $sResult = "Начало массива" & @CRLF
    Local $bRunning = True

    While $bRunning
        ; Добавляем начало уровней
        For $i = 0 To $iDimensions - 1
            If Not $aStartedLevels[$i] Then
                $sResult &= _StringRepeat("  ", $i) & "Уровень " & ($i + 1) & " - Начало" & @CRLF
                $aStartedLevels[$i] = True
            EndIf
        Next

        ; Добавляем текущий элемент массива
        If $iDimensions = 1 Then
            $sResult &= _StringRepeat("  ", $iDimensions) & $avArray[$aCounters[0]] & @CRLF
        ElseIf $iDimensions = 2 Then
            $sResult &= _StringRepeat("  ", $iDimensions) & $avArray[$aCounters[0]][$aCounters[1]] & @CRLF
        ElseIf $iDimensions = 3 Then
            $sResult &= _StringRepeat("  ", $iDimensions) & $avArray[$aCounters[0]][$aCounters[1]][$aCounters[2]] & @CRLF
        Else
            Local $sAccess = "$avArray"
            For $i = 0 To $iDimensions - 1
                $sAccess &= "[" & $aCounters[$i] & "]"
            Next
            $sResult &= _StringRepeat("  ", $iDimensions) & Execute($sAccess) & @CRLF
        EndIf

        ; Обновляем счётчики и обрабатываем завершение уровней
        For $i = $iDimensions - 1 To 0 Step -1
            If $aCounters[$i] < $aBounds[$i] - 1 Then
                $aCounters[$i] += 1
                ; Сбрасываем состояния начатых уровней для уровней ниже
                For $j = $i + 1 To $iDimensions - 1
                    $aStartedLevels[$j] = False
                Next
                ExitLoop
            Else
                ; Завершаем уровень
                $aCounters[$i] = 0
                $sResult &= _StringRepeat("  ", $i) & "Уровень " & ($i + 1) & " - Конец" & @CRLF
                $aStartedLevels[$i] = False
                If $i = 0 Then
                    $bRunning = False ; Завершаем весь цикл, если завершился первый уровень
                EndIf
            EndIf
        Next
    WEnd

    ; Завершаем массив
    $sResult &= "Конец массива"
    Return $sResult
EndFunc
Но хочется, чтобы было похоже на вывод в PHP функции print_r. Пока у меня не получается отформатировать, да и подсчет индексов потерялся.
Код:
Func _ArrayToStringPHPStyle(Const ByRef $avArray)
    If Not IsArray($avArray) Then Return SetError(1, 0, '')

    Local $iDimensions = UBound($avArray, 0) ; Определяем количество измерений
    Local $aCounters[$iDimensions] ; Массив-счётчик для индексов
    Local $aBounds[$iDimensions] ; Массив границ для каждого уровня
    Local $aStartedLevels[$iDimensions] = [False] ; Отслеживаем, начат ли уровень

    ; Заполняем границы
    For $i = 0 To $iDimensions - 1
        $aBounds[$i] = UBound($avArray, $i + 1)
        $aCounters[$i] = 0
    Next

    Local $sResult = "Array (" & @CRLF
    Local $bRunning = True

    While $bRunning
        ; Добавляем начало уровней
        For $i = 0 To $iDimensions - 1
            If Not $aStartedLevels[$i] Then
                $sResult &= _StringRepeat("    ", $i) & "[" & $aCounters[$i] & "] => Array (" & @CRLF
                $aStartedLevels[$i] = True
            EndIf
        Next

        ; Добавляем текущий элемент массива
        Local $sAccess = "$avArray"
        For $i = 0 To $iDimensions - 1
            $sAccess &= "[" & $aCounters[$i] & "]"
        Next
        $sResult &= _StringRepeat("    ", $iDimensions) & "[" & $aCounters[$iDimensions - 1] & "] => " & Execute($sAccess) & @CRLF

        ; Обновляем счётчики и обрабатываем завершение уровней
        For $i = $iDimensions - 1 To 0 Step -1
            If $aCounters[$i] < $aBounds[$i] - 1 Then
                $aCounters[$i] += 1
                ; Сбрасываем состояния начатых уровней для уровней ниже
                For $j = $i + 1 To $iDimensions - 1
                    $aStartedLevels[$j] = False
                Next
                ExitLoop
            Else
                ; Завершаем уровень
                $aCounters[$i] = 0
                $sResult &= _StringRepeat("    ", $i) & ")" & @CRLF
                $aStartedLevels[$i] = False
                If $i = 0 Then
                    $bRunning = False ; Завершаем весь цикл, если завершился первый уровень
                EndIf
            EndIf
        Next
    WEnd

    ; Завершаем массив
    $sResult &= ")" & @CRLF
    Return $sResult
EndFunc
Голова кругом идет, не пойму в чем затык. Но тут добавляется лишний уровень и не печатаются индексы уровня. Только индексы последнего.
А вообще тренируюсь на таком массиве:
Код:
Local $aArray[2][2][3] = [ _
    [["A1-1", "A1-2", "A1-3"], _
     ["A2-1", "A2-2", "A2-3"]], _
    [["B1-1", "B1-2", "B1-3"], _
     ["B2-1", "B2-2", "B2-3"]] _
]

Пока что получаю вот такой вывод в печать:
Код:
Array (
[0] => Array (
    [0] => Array (
        [0] => Array (
            [0] => A1-1
            [1] => A1-2
            [2] => A1-3
        )
        [0] => Array (
            [0] => A2-1
            [1] => A2-2
            [2] => A2-3
        )
    )
    [0] => Array (
        [0] => Array (
            [0] => B1-1
            [1] => B1-2
            [2] => B1-3
        )
        [0] => Array (
            [0] => B2-1
            [1] => B2-2
            [2] => B2-3
        )
    )
)
)
а хочется такой:
Код:
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => A1-1
                    [1] => A1-2
                    [2] => A1-3
                )

            [1] => Array
                (
                    [0] => A2-1
                    [1] => A2-2
                    [2] => A2-3
                )

        )

    [1] => Array
        (
            [0] => Array
                (
                    [0] => B1-1
                    [1] => B1-2
                    [2] => B1-3
                )

            [1] => Array
                (
                    [0] => B2-1
                    [1] => B2-2
                    [2] => B2-3
                )

        )

)
Сообщение автоматически объединено:

Вот результат эксперимента «на табуретке» :acute:
Пока для начала переделал ваш набор в одну функцию:
Код:
#include <Array.au3>
#include <String.au3>

; Объявляем массив
Local $aArray[2][2][3] = [ _
    [["A1-1", "A1-2", "A1-3"], _
     ["A2-1", "A2-2", "A2-3"]], _
    [["B1-1", "B1-2", "B1-3"], _
     ["B2-1", "B2-2", "B2-3"]] _
]

Func PrintArrayInfo($aArray)
    ; Проверка на массив
    If Not IsArray($aArray) Then
        ConsoleWrite("Ошибка: Переданная переменная не является массивом." & @CRLF)
        Return
    EndIf

    ; Определяем размерности и индексы
    Local $iDimensions = UBound($aArray, 0)
    Local $aDims[1 + $iDimensions]
    Local $aIndx[1 + $iDimensions]
    Local $sResult = ""
    Local $k = 0

    ; Заполнение таблицы размерностей
    $aDims[0] = $iDimensions
    For $i = 1 To $iDimensions
        $aDims[$i] = UBound($aArray, $i)
    Next

    ; Инициализация индексов
    For $i = 1 To $iDimensions
        $aIndx[$i] = 0
    Next
    $aIndx[$iDimensions] = -1 ; Фиктивный индекс для первого вызова

    ; Формирование общей информации
    Local $iTotal = 1
    Local $sDims = ""
    For $i = 1 To $iDimensions
        $iTotal *= $aDims[$i]
        $sDims &= "[" & $aDims[$i] & "]"
    Next
    $sResult &= StringFormat("Размерность  : %s\n", $sDims)
    $sResult &= StringFormat("Число эл-тов : %u\n", $iTotal)

    ; Основной цикл обхода элементов массива
    While True
        ; Пропускаем фиктивный индекс
        If $aIndx[$iDimensions] = -1 Then
            $aIndx[$iDimensions] = 0
            ContinueLoop
        EndIf

        ; Генерация индексов
        Local $sArr_Item = ""
        For $i = 1 To $aDims[0]
            $sArr_Item &= "[" & $aIndx[$i] & "]"
        Next

        ; Получение значения текущего элемента
        $k += 1
        Local $sValue = Execute('$aArray' & $sArr_Item)
        $sResult &= StringFormat("%3u. Arr%s = %s\n", $k, $sArr_Item, $sValue)

        ; Обновление индексов
        For $i = $iDimensions To 1 Step -1
            $aIndx[$i] += 1
            If $aIndx[$i] < $aDims[$i] Then ExitLoop
            $aIndx[$i] = 0
            If $i = 1 Then
                ; Завершение обхода
                ConsoleWrite($sResult)
                Return
            EndIf
        Next
    WEnd
EndFunc

; Выводим содержимое массива
PrintArrayInfo($aArray)
Буду пробовать переделать дальше под свои нужды.
 
Последнее редактирование:
Верх