За последние 24 часа нас посетили 22889 программистов и 1260 роботов. Сейчас ищут 766 программистов ...

Рекурсивный обход массива с возвратом значений

Тема в разделе "PHP для новичков", создана пользователем voii, 30 июл 2018.

  1. voii

    voii Новичок

    С нами с:
    30 июл 2018
    Сообщения:
    9
    Симпатии:
    3
    Здравствуйте!
    Имеется массив
    Код (Text):
    1. array(1) {
    2.   ["Группа"]=>
    3.   array(3) {
    4.     [0]=>
    5.     array(5) {
    6.       ["Ид"]=>
    7.       string(36) "e9f69781-9de1-4610-9ddb-8e81779832cb"
    8.       ["НомерВерсии"]=>
    9.       string(12) "AAAAAQAAAAI="
    10.       ["ПометкаУдаления"]=>
    11.       string(5) "false"
    12.       ["Наименование"]=>
    13.       string(35) "Взрослая коллекция"
    14.       ["Группы"]=>
    15.       array(1) {
    16.         ["Группа"]=>
    17.         array(3) {
    18.           [0]=>
    19.           array(4) {
    20.             ["Ид"]=>
    21.             string(36) "054a4c71-ce5a-48c2-89b0-e5e7671a2b30"
    22.             ["НомерВерсии"]=>
    23.             string(12) "AAAAAQAAAAQ="
    24.             ["ПометкаУдаления"]=>
    25.             string(5) "false"
    26.             ["Наименование"]=>
    27.             string(18) "Демисезон"
    28.           }
    29.           [1]=>
    30.           array(4) {
    31.             ["Ид"]=>
    32.             string(36) "4cc716d5-e445-4818-8b6e-3d2ff8e777a9"
    33.             ["НомерВерсии"]=>
    34.             string(12) "AAAAAQAAAAU="
    35.             ["ПометкаУдаления"]=>
    36.             string(5) "false"
    37.             ["Наименование"]=>
    38.             string(8) "Зима"
    39.           }
    40.           [2]=>
    41.           array(4) {
    42.             ["Ид"]=>
    43.             string(36) "f16031ef-f81f-4c75-9753-23fdac46c8d3"
    44.             ["НомерВерсии"]=>
    45.             string(12) "AAAAAQAAAAM="
    46.             ["ПометкаУдаления"]=>
    47.             string(5) "false"
    48.             ["Наименование"]=>
    49.             string(8) "Лето"
    50.           }
    51.         }
    52.       }
    53.     }
    54.     [1]=>
    55.     array(5) {
    56.       ["Ид"]=>
    57.       string(36) "1b291b7a-53dc-4f73-a76e-de1db754e3e4"
    58.       ["НомерВерсии"]=>
    59.       string(12) "AAAAAQAAAAY="
    60.       ["ПометкаУдаления"]=>
    61.       string(5) "false"
    62.       ["Наименование"]=>
    63.       string(33) "Детская коллекция"
    64.       ["Группы"]=>
    65.       array(1) {
    66.         ["Группа"]=>
    67.         array(2) {
    68.           [0]=>
    69.           array(4) {
    70.             ["Ид"]=>
    71.             string(36) "ca7f3385-3452-468f-b587-314c7c211f6d"
    72.             ["НомерВерсии"]=>
    73.             string(12) "AAAAAQAAAAg="
    74.             ["ПометкаУдаления"]=>
    75.             string(5) "false"
    76.             ["Наименование"]=>
    77.             string(18) "Демисезон"
    78.           }
    79.           [1]=>
    80.           array(4) {
    81.             ["Ид"]=>
    82.             string(36) "071d5e60-f256-4581-9b43-a386f1a42c96"
    83.             ["НомерВерсии"]=>
    84.             string(12) "AAAAAQAAAAc="
    85.             ["ПометкаУдаления"]=>
    86.             string(5) "false"
    87.             ["Наименование"]=>
    88.             string(8) "Лето"
    89.           }
    90.         }
    91.       }
    92.     }
    93.     [2]=>
    94.     array(5) {
    95.       ["Ид"]=>
    96.       string(36) "81868932-dc49-4d02-8e58-0d233eaa3401"
    97.       ["НомерВерсии"]=>
    98.       string(12) "AAAAAQAAAAk="
    99.       ["ПометкаУдаления"]=>
    100.       string(5) "false"
    101.       ["Наименование"]=>
    102.       string(20) "Распродажи"
    103.       ["Группы"]=>
    104.       array(1) {
    105.         ["Группа"]=>
    106.         array(2) {
    107.           [0]=>
    108.           array(4) {
    109.             ["Ид"]=>
    110.             string(36) "13e6e290-f603-4819-a1c3-bf51ed1f7c20"
    111.             ["НомерВерсии"]=>
    112.             string(12) "AAAAAQAAAAo="
    113.             ["ПометкаУдаления"]=>
    114.             string(5) "false"
    115.             ["Наименование"]=>
    116.             string(15) "Все по 350"
    117.           }
    118.           [1]=>
    119.           array(4) {
    120.             ["Ид"]=>
    121.             string(36) "5bef86ce-cecd-4f88-9313-5d5aa1aad32c"
    122.             ["НомерВерсии"]=>
    123.             string(12) "AAAAAQAAAAs="
    124.             ["ПометкаУдаления"]=>
    125.             string(5) "false"
    126.             ["Наименование"]=>
    127.             string(15) "Все по 550"
    128.           }
    129.         }
    130.       }
    131.     }
    132.   }
    133. }
    нужно обойти рекурсивно и взять значения "ид" и "наименование".
    Сам процесс обхода реализую функцией
    Код (Text):
    1. getGroupsRecursive($arrGroupsInXml)
    2.     {
    3.         foreach ($arrGroupsInXml as $item) {
    4.             if (is_array($item)) {
    5.                 getGroupsRecursive($item);
    6.             } else {
    7.                 echo $item."<br>";
    8.             }
    9.         }
    10.     }
    получаю результат:
    e9f69781-9de1-4610-9ddb-8e81779832cb
    AAAAAQAAAAI=
    false
    Взрослая коллекция
    054a4c71-ce5a-48c2-89b0-e5e7671a2b30
    AAAAAQAAAAQ=
    false
    Демисезон
    4cc716d5-e445-4818-8b6e-3d2ff8e777a9
    AAAAAQAAAAU=
    false
    Зима
    f16031ef-f81f-4c75-9753-23fdac46c8d3
    AAAAAQAAAAM=
    false
    Лето
    1b291b7a-53dc-4f73-a76e-de1db754e3e4
    AAAAAQAAAAY=
    false
    Детская коллекция
    ca7f3385-3452-468f-b587-314c7c211f6d
    AAAAAQAAAAg=
    false
    Демисезон
    071d5e60-f256-4581-9b43-a386f1a42c96
    AAAAAQAAAAc=
    false
    Лето
    81868932-dc49-4d02-8e58-0d233eaa3401
    AAAAAQAAAAk=
    false
    Распродажи
    13e6e290-f603-4819-a1c3-bf51ed1f7c20
    AAAAAQAAAAo=
    false
    Все по 350
    5bef86ce-cecd-4f88-9313-5d5aa1aad32c
    AAAAAQAAAAs=
    false
    Все по 550

    Подскажите как это всё можно вернуть через return?
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    ну рекурсия как раз и состоит в том, чтобы это всё вернуть разом, скопив через все рекурсивные вызовы.

    может тебе лучше это в разделе разовой платной работы разместить?
     
  3. voii

    voii Новичок

    С нами с:
    30 июл 2018
    Сообщения:
    9
    Симпатии:
    3
    Да мне самому разобраться хочется...
    Тем более что вы пишете "вернуть", хочется вернуть, не в браузер распечатать, а переменой, массивом и т.д. понять как.
    А через буферизацию, с точки зрения не "кривого кода" можно реализовать?
    Как реализовать я знаю, я имею ввиду именно именно с точки зрения правильности.
    --- Добавлено ---
    Или лучше через глобальную переменную.
     
  4. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    Добавь вторым параметром ссылку на выходной массив и передавай его во всех рекурсивных вызовов, в нём и накапливай
     
  5. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    Или array_merge с результатом рекрсивного вызова
     
  6. voii

    voii Новичок

    С нами с:
    30 июл 2018
    Сообщения:
    9
    Симпатии:
    3
    Большое вам спасибо! Вариант со ссылкой отлично работает, всё собирает и потом ретурном замечательно передаёт во внешнюю функцию.
     
    igordata и mkramer нравится это.
  7. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    Приятно, когда достаточно указать направление, без разжёвывания
     
  8. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    Ещё можно было бы записывать результат в переменную внутри функции и по выходу из рекурсии её возвращать.
     
  9. voii

    voii Новичок

    С нами с:
    30 июл 2018
    Сообщения:
    9
    Симпатии:
    3
    к сожалению просто в переменную/массив и т.д. не получается, записывается только верхний уровень, вложенные затираются (
     
  10. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    если в строку конкатенируй или позднее статическое связывание
     
  11. voii

    voii Новичок

    С нами с:
    30 июл 2018
    Сообщения:
    9
    Симпатии:
    3
    со строками не очень удобно, нужно потом в массив их переделывать, лишний код, а статичексое связывание пробывал, так же работает. В любом случае всем спасибо, очень быстро и верно направили. А то иногда ступор в решении какой-то задачи приходит и не видишь перед собой очивидных решений.
     
  12. mahmuzar

    mahmuzar Старожил

    С нами с:
    6 апр 2012
    Сообщения:
    4.632
    Симпатии:
    425
    Адрес:
    РД, г. Махачкала.
    А это тут каким боком?
     
  13. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    Меня часто посещают бредовые идеи :rolleyes:
     
  14. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    Да ладно пацаны вы чё, серьезно что ли
    PHP:
    1. <?php
    2. function getKeyVals($arr, $key) {
    3.     foreach ($arr as $k => $v) {
    4.         if ($k === $key) {
    5.           yield $v;
    6.         }
    7.         else if (is_array($v)) {
    8.             foreach (getKeyVals($v, $key) as $v2) {
    9.                 yield $v2;
    10.             }
    11.         }
    12.     }
    13. }
    14.  
    15. $data = [
    16.         [
    17.             'name' => 'A',
    18.             'value' => 1
    19.         ],
    20.         [
    21.             'name' => 'B',
    22.             'value' => 2
    23.         ],
    24.         [
    25.             'name' => 'C',
    26.             'value' => [
    27.                 'name' => 'X1',
    28.                 'value' => 3
    29.                 ],
    30.                 [
    31.                 'name' => 'X2',
    32.                 'value' => 4
    33.                 ],
    34.         ]
    35.     ];
    36.  
    37. foreach (getKeyVals($data, 'name') as $r) {
    38.    var_dump($r);
    39. }
    Код (Text):
    1. string(1) "A"
    2. string(1) "B"
    3. string(1) "C"
    4. string(2) "X1"
    5. string(2) "X2"
    Генераторы с нами с 5.5.0.
    https://php.ru/forum/threads/generatory-yield.53547/
     
    mkramer и igordata нравится это.
  15. Roma78

    Roma78 Новичок

    С нами с:
    25 окт 2020
    Сообщения:
    2
    Симпатии:
    1
    array_walk_recursive
     
    [vs] нравится это.
  16. Roma78

    Roma78 Новичок

    С нами с:
    25 окт 2020
    Сообщения:
    2
    Симпатии:
    1
    or

    Код (Text):
    1. private function array_filter_recursive (array $array, callable $callback) {
    2.     foreach ($array as $k => $v) {
    3.         if (!$array[$k] = (is_array($v) ? $this->array_filter_recursive($v, $callback) : ($callback($v, $k) ? $v : false))) unset($array[$k]);
    4.     }
    5.  
    6.     return $array;
    7. }
    8.  
    9.  
    10. $outputs = $this->array_filter_recursive($inputs, function ($v, $k) {
    11.     return ($k == 'id' || $k === 'name');
    12. });
     
  17. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    static
    PHP:
    1. function getGroupsRecursive($arrGroupsInXml) {
    2.         static $result = [];
    3.  
    4.         foreach ($arrGroupsInXml as $item) {
    5.             if (is_array($item)) {
    6.                 getGroupsRecursive($item);
    7.             } else {
    8.                 $result[] = $item;
    9.             }
    10.         }
    11.  
    12.        return $result;
    13.   }
     
  18. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.554
    Симпатии:
    1.754
    @villiwalla Не лучшая идея, потому что при повторном вызове будет уже наполненный ваш $result старыми значениями. Мне, в последнее время, нравится делать такие вещи так:

    PHP:
    1. function getGroupsRecursive($arrGroupsInXml){
    2.    $result = [];
    3.    $recScan = function ($items) use (&$recScan, &$result) {
    4.    
    5.           foreach ($items as $item) {
    6.             if (is_array($item)) {
    7.                 $recScan($item);
    8.             } else {
    9.                 $result[] = $item;
    10.             }
    11.         }
    12.    };
    13.    $recScan($arrGroupsInXml);
    14.    return $result;
    15. }
    Не вникал в смысл функции
     
    villiwalla нравится это.