Можно ли посчитать количество измерений в массиве? - PullRequest
8 голосов
/ 26 августа 2010

Я хочу знать уровень массива во время его создания.

Код перебирает кучу каталогов для создания массивного многомерного массива.

Поскольку массив создается, я хочу знать, насколько глубоко я в нем.

1    2    3    4
---------------------
Root
     A
          A2
          A3
          A4
               A4a
     B
          B2
          B3
     C
     D
     E
          E2
               E2a
          E3

В приведенном выше примере корневой каталог находится на уровне 1. Все заглавные буквы находятся на уровне 2.Все заглавные буквы с номером находятся на уровне 3. Все заглавные буквы с номером и строчные буквы находятся на уровне 4.

Поскольку я строю массив, есть ли способ узнать, какой уровеньЯ в?Массив создается с помощью рекурсивной функции.

Это вопрос PHP.

Ответы [ 5 ]

5 голосов
/ 27 августа 2010

Это может быть касательно вашего вопроса о массиве, но вы можете убить двух зайцев одним выстрелом, используя рекурсивный итератор каталогов.

$path_to_root = __DIR__;
$directories  = new ParentIterator(new RecursiveDirectoryIterator($path_to_root, RecursiveDirectoryIterator::CURRENT_AS_SELF));
$iterator     = new RecursiveIteratorIterator($directories, RecursiveIteratorIterator::SELF_FIRST);

foreach ($iterator as $item)
{
    printf("%d %s\n", $iterator->getDepth() + 1, $item->getSubPathname());
}

Что бы вывести что-то вроде:

1 Root
2 Root/A
3 Root/A/A2
3 Root/A/A3
3 Root/A/A4
4 Root/A/A4/A4a
2 Root/B
3 Root/B/B2
3 Root/B/B3
2 Root/C
2 Root/D
2 Root/E
3 Root/E/E2
4 Root/E/E2/E2a
3 Root/E/E3

Как видите, RecursiveIteratorIterator::getDepth() используется для получения текущей глубины рекурсивного итератора, что является причиной для предложения такого подхода.


Альтернатива (если вы должны использовать массив)

Предположим, что ваша структура массива выглядит примерно так:

$dirs = array(
    'Root' => array(
        'A' => array(
            'A2' => array(),
            'A3' => array(),
            'A4' => array(
                'A4a' => array(),
            ),
        ),
        'B' => array(
            'B2' => array(),
            'B3' => array(),
        ),
        'C' => array(),
        'D' => array(),
        'E' => array(
            'E2' => array(
                'E2a' => array(),
            ),
            'E3' => array(),
        ),
    ),
);

Тогда можно использовать очень похожий подход к получению значений от рекурсивного итератора каталога (но на этот раз с рекурсивным итератором массива). Быстрый цикл по «родительским» массивам может дать нам «путь» от текущего элемента до корня.

$recursive = new ParentIterator(new RecursiveArrayiterator($dirs));
$iterator  = new RecursiveIteratorIterator($recursive, RecursiveIteratorIterator::SELF_FIRST);

foreach ($iterator as $item)
{
    // Build path from "parent" array keys
    for ($path = "", $i = 0; $i <= $iterator->getDepth(); $i++) {
        $path .= "/" . $iterator->getSubIterator($i)->key();
    }
    // Output depth and "path"
    printf("%d %s\n", $iterator->getDepth() + 1, ltrim($path, "/"));
}

Вывод будет таким же, как и предыдущий для итератора каталога.

TL; DR Мы можем использовать рекурсивные итераторы из SPL-итераторов , чтобы упростить работу с рекурсивными / глубокими структурами.

TL; DR; TL; DR SPL, черт возьми, да!

3 голосов
/ 26 августа 2010

Это должно сделать:

function array_depth($array) {
    $max_depth = 1;

    foreach ($array as $value) {
        if (is_array($value)) {
            $depth = array_depth($value) + 1;

            if ($depth > $max_depth) {
                $max_depth = $depth;
            }
        }
    }

    return $max_depth;
}
3 голосов
/ 26 августа 2010

Один быстрый и простой ответ - просто добавить параметр «глубина» в вашу функцию и увеличить его при вызове самой функции.

0 голосов
/ 26 августа 2010

Возможно, вы задаете не тот вопрос. Какова конечная цель? Например, в SPL есть класс RecursiveDirectoryIterator , может, это подойдет вам? Создание большого многомерного массива потребляет много памяти, поэтому, может быть, достаточно просто рекурсивно перебирать все эти файлы?

0 голосов
/ 26 августа 2010
function calc_dimensions(array $array) {
    $dimensions = 1;
    $max = 0;
    foreach ($array as $value) {
        if (is_array($value)) {
            $subDimensions = calc_dimensions($value);
            if ($subDimensions > $max) {
                $max = $subDimensions;
            }
        }
    }

    return $dimensions+$max;
}

$array = array(
    array(
        array(
            4 => 5,
            array(
                6 => 6
            )
        )
    ),
    1 => 5
);

echo calc_dimensions($array)."\n";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...