PHP - Преобразование многомерного массива в 2D-массив с точечными клавишами

Ну, по крайней мере, в nhibernate session.Get (id) будет загружать объект из базы данных, а session.Load (id) создает для него прокси-объект, не покидая ваш сервер. Работает точно так же, как и все остальные лениво загруженные объекты в ваших POCOs (или POJO :). Затем вы можете использовать этот прокси-сервер в качестве ссылки на сам объект, чтобы создавать отношения и т. Д.

Подумайте об этом как о наличии объекта, в котором хранится только Id, и который загрузит остальное, если вам когда-нибудь понадобится. Если вы просто передаете его для создания отношений (например, FK), идентификатор - это все, что вам когда-либо понадобится.

23
задан TheCheese 3 May 2012 в 02:31
поделиться

3 ответа

кодек

$ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($myArray));
$result = array();
foreach ($ritit as $leafValue) {
    $keys = array();
    foreach (range(0, $ritit->getDepth()) as $depth) {
        $keys[] = $ritit->getSubIterator($depth)->key();
    }
    $result[ join('.', $keys) ] = $leafValue;
}

выход

Array
(
    [key1] => value1
    [key2.subkey] => subkeyval
    [key3] => value3
    [key4.subkey4.subsubkey4] => subsubkeyval4
    [key4.subkey4.subsubkey5] => subsubkeyval5
    [key4.subkey5] => subkeyval5
)

демо: http://codepad.org/YiygqxTM

Мне нужно иди, но если тебе понадобится объяснение этого завтра, спроси меня.

67
ответ дан goat 3 May 2012 в 02:31
поделиться

Уже есть ответ с RecursiveIteratorIterator . Но вот более оптимальное решение, которое избегает использования вложенных циклов :

$iterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($arr),
    RecursiveIteratorIterator::SELF_FIRST
);
$path = [];
$flatArray = [];

foreach ($iterator as $key => $value) {
    $path[$iterator->getDepth()] = $key;

    if (!is_array($value)) {
        $flatArray[
            implode('.', array_slice($path, 0, $iterator->getDepth() + 1))
        ] = $value;
    }
}

Здесь необходимо сделать несколько замечаний. Обратите внимание на использование константы RecursiveIteratorIterator::SELF_FIRST здесь. Это важно, поскольку значение по умолчанию - RecursiveIteratorIterator::LEAVES_ONLY, которое не позволяет нам получить доступ ко всем ключам. Таким образом, с этим постоянным набором мы начинаем с верхнего уровня массива и углубляемся. Этот подход позволяет нам сохранять историю ключей и подготавливать ключ, когда мы разбираем листы, используя метод RecursiveIteratorIterator::getDepth .

Вот рабочая демонстрация.

3
ответ дан sevavietl 3 May 2012 в 02:31
поделиться

Это еще один подход, аналогичный Blafrat выше - но он обрабатывает массивы просто как значения.

 function dot_flatten($input_arr, $return_arr = array(), $prev_key = '')
 {
     foreach ($input_arr as $key => $value)
     {
        $new_key = $prev_key . $key;

        // check if it's associative array 99% good
        if (is_array($value) && key($value) !==0 && key($value) !==null)
        {
            $return_arr = array_merge($return_arr, dot_flatten($value, $return_arr, $new_key . '.'));
        }
        else
        {
            $return_arr[$new_key] = $value;
        }
    }

    return $return_arr;
}

(Единственный случай, который не поймал бы, это когда у вас было значение, которое было ассоциативным, но первый ключ был 0.)

Обратите внимание, что RecursiveIteratorIterator может быть медленнее, чем обычная рекурсивная функция. https://xenforo.com/community/threads/php-spl-why-is-recursiveiteratoriterator-100x-slower-than-recursive-search.57572/

В этом случае используется В примере массива, приведенном для 1000 итераций php5.6, этот код работает в два раза быстрее (рекурсивно = .032 против интегратора = .062) - но в большинстве случаев разница, вероятно, незначительна. В основном я предпочитаю рекурсивную, потому что нахожу логику Итератора без необходимости сложной для такого простого случая использования, как этот.

1
ответ дан Yehosef 3 May 2012 в 02:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: