За последние 24 часа нас посетили 22144 программиста и 1686 роботов. Сейчас ищут 1585 программистов ...

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

Тема в разделе "Вопросы от блондинок", создана пользователем Dmitriy A. Arteshuk, 19 янв 2012.

  1. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    вопрос из серии "то ли лыжи не едут, толи одно из двух.....

    Код (Text):
    1. Array
    2. (
    3.     [0] => Array
    4.         (
    5.             [id] => 15
    6.             [pid] => 0
    7.             [module_id] => comments1
    8.                 (
    9.                  [0] => Array
    10.                         (
    11.                             [id] => 16
    12.                             [pid] => 15
    13.                             [module_id] => comments1
    14.                                 (
    15.                                     [0] => Array
    16.                                         (
    17.                                             [id] => 21
    18.                                             [pid] => 16
    19.                                             [module_id] => comments1
    20.                                         )
    21.  
    22.                                 )
    23.  
    24.                         )
    25.  
    26.                 )
    27.  
    28.         )
    Подскажите пожалуйста, как можно посчитать на "каком уровне вложенности" от "корневого массива" находится элемент с id 21 (сейчас он на третьем) (ну вобщем любой элемент, ибо функция должна быть универсальной, вычислять любой уровень вложенности...

    если что, то нужно это для построения "дерева"...

    записать сразу при добавлении записи в БД уровень от корня дерева нет возможности, поэтому надо посчитать его при извлечении.....

    Хотя может и можно при добавлении записи, но я не знаю как :(
     
  2. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ключевое слово - рекурсия =)
     
  3. asokol

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

    С нами с:
    17 янв 2012
    Сообщения:
    162
    Симпатии:
    0
    Сделать print_r с return=true, посчитать количество открывающих скобок на отдельной строке до нужного элемента и вычесть количество закрывающих скобок на отдельной строке до нужного элемента. :) И вычесть 1.

    Ой, а еще можно посчитать количество \t, которые идут до [id] => 21 и поделить пополам (наверное). %)
     
  4. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    спасибо за наводку, убежал гуглить :)
     
  5. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    продолжаем делать из себя дуру :)

    Код (Text):
    1. function make_tree()
    2. {
    3.     $tree = array();
    4.  
    5.     $query = mysql_query('SELECT * FROM `comments`');
    6.     if (! $query) return $tree;
    7.  
    8.     $nodes = array();
    9.     $keys = array();
    10.     while (($node = mysql_fetch_assoc($query)))
    11.     {
    12.         $nodes[$node['id']] =& $node; //заполняем список веток записями из БД
    13.         $keys[] = $node['id']; //заполняем список ключей(ID)
    14.         unset($node);
    15.     }
    16.     mysql_free_result($query);
    17.  
    18.     foreach ($keys as $key)
    19.     {
    20.         /**
    21.          * если нашли главную ветку(или одну из главных), то добавляем
    22.          * её в дерево
    23.          */
    24.         if ($nodes[$key]['pid'] === '0')
    25.             $tree[] =& $nodes[$key];
    26.  
    27.         /**
    28.          * else находим родительскую ветку и добавляем текущую
    29.          * ветку к дочерним элементам родит.ветки.
    30.          */
    31.         else
    32.         {
    33.             if (isset($nodes[ $nodes[$key]['pid'] ])) //на всякий случай, вдруг в базе есть потерянные ветки
    34.             {
    35.                 if (! isset($nodes[ $nodes[$key]['pid'] ]['nodes'])) //если нет поля определяющего наличие дочерних веток
    36.                     $nodes[ $nodes[$key]['pid'] ]['nodes'] = array(); //то добавляем к записи узел (массив дочерних веток) на данном этапе
    37.  
    38.                 $nodes[ $nodes[$key]['pid'] ]['nodes'][] =& $nodes[$key];
    39.             }
    40.         }
    41.     }
    42.  
    43.     return $tree;
    44. }
    $abc = $this ->make_tree(0, 0); - возвращает то же что я написал в первом посте.....

    ЗЫ чую у меня получается :)
     
  6. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Код (Text):
    1. <?php
    2. $level = 0;
    3. $v = current($array);
    4. while (is_array($v)) {
    5.      $level++;
    6.      $v = current($array);
    7. }
    8. echo $level;
     
  7. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    ну что ж вы за люди то такие :(
    vs - от Вас не ожидал.... :(

    В любом случае спасибо за науку, рекурсию мне видимо пока не осилить, будем "плюсадинить" в БД при записи....
     
  8. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Чо? Это идеальное решение сабжа! Адаптируй под структуру своего массива
     
  9. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    это зацикливает все на свете :)

    во всяком случае в том виде, в котором Вы написали...

    ЗЫ сервак почти упал :)
     
  10. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Ну да блин, внутри цикла надо $v = current($v); очевидно же
     
  11. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    добавить isset($v['id'])...
     
  12. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    это вам, гуру, очевидно :) спасибо!
     
  13. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ...и после этого $v['id'] == $iskomoe...
     
  14. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    все замечательно, получил я свои 1, 2, 3, но появилось одно НО:

    если на входе такой массив


    Код (Text):
    1. Array
    2. (
    3.     [0] => Array
    4.         (
    5.             [id] => 15
    6.             [pid] => 0
    7.             [module_id] => comments1
    8.                 (
    9.                  [0] => Array
    10.                         (
    11.                             [id] => 16
    12.                             [pid] => 15
    13.                             [module_id] => comments1
    14.                          )
    15.                   [1] => Array
    16.                          (
    17.                             [id] => 21
    18.                             [pid] => 16
    19.                             [module_id] => comments1
    20.                          )
    21.                )
    22.         )
    23. )

    то на выходе я должен получить 1,2,2.....а я получаю 1,2,3....

    как исправить?
     
  15. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ты должен получить ровно ДВА. =) покажи код
     
  16. asokol

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

    С нами с:
    17 янв 2012
    Сообщения:
    162
    Симпатии:
    0
    Может я чего-то не понимаю, но:
    http://php.net/manual/ru/function.current.html
    Функция current() просто возвращает значение элемента массива, на который указывает его внутренний указатель. Она не перемещает указатель куда бы то ни было. Если внутренний указатель находится за пределами списка элементов или массив пуст, current() возвращает FALSE.

    Ну и даже если добавить next или же заменить все на each (как рекомендуется ниже на странице, указанной выше), то это будет работать только с одномерным массивом.

    Дмитрий, а Вы можете сформулировать корректно, что надо в результате получить? Надо только вычислить вложенность или же что-то еще? Если только вложенность, то какие исходные данные? Насколько я понимаю, массива, который Вы описали в начале топика, у Вас изначально нет, верно?
     
  17. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    точно.
     
  18. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Мой пример считает вложенность труъ-многомерного массива, в котором до последнего уровня _только_ вложенные массивы, и только на последнем - данные. Таким образом, он погружаются в направлении $arr[0][0][0][0]... пока этот самый [0] будет массивом. Если $arr[0][0][0] - массив, а $arr[0][1] - нет, то это какая угодно структура, но не многомерный массив.
     
  19. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    Код (Text):
    1. $level = 0;
    2. $v = current($nodes);
    3.    while (is_array($v)) {
    4.         $level++;
    5.         $v = current($v);
    6. }
    7.  echo $level."|<br>";
     
  20. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    и каким образом ты умудряешься получить значения через запятые и вобще более одного значения? данный код такие фокусы не позволяет =)
     
  21. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    asokol

    совершенно верно!!! Смотрите:

    я выбираю данные из БД (если конкретно,то комменты к определенной статье) далее

    Код (Text):
    1.  
    2. $tree = array();
    3. $nodes = array();
    4. $keys = array();
    5.            
    6. while ($row = mysql_fetch_assoc($result))
    7. {
    8.         $nodes[$row['id']] =& $row; //заполняем список веток записями из БД
    9.     $keys[] = $row['id']; //заполняем список ключей(ID)
    10.     unset($row);
    11. }
    12. $level = 0;
    13. foreach ($keys as $key)
    14. {
    15.        if ($nodes[$key]['pid'] === '0')
    16.             $tree[] =& $nodes[$key];
    17. else
    18.         {
    19.             if (isset($nodes[ $nodes[$key]['pid'] ])) //на всякий случай, вдруг в базе есть потерянные ветки
    20.             {
    21.                 if (! isset($nodes[ $nodes[$key]['pid'] ]['nodes'])) //если нет поля определяющего наличие дочерних веток
    22.         {
    23.                     $nodes[ $nodes[$key]['pid'] ]['nodes'] = array(); //то добавляем к записи узел (массив дочерних веток) на данном этапе
    24.         }
    25.                 $nodes[ $nodes[$key]['pid'] ]['nodes'][] =& $nodes[$key];
    26.             }
    27. $v = current($nodes);
    28. while (is_array($v)) {
    29. $level++;
    30. $v = current($v);}
    31. echo $level."|<br>";
    32.  
    33. // в результате в $tree получается массив из корневого топика. "уровень вложенности" этого массива произволен и может быть каким угодно.
    34. }
    $level верно считает, только если массив как в первом посте. 1,2,3

    если же массив имеет другую структуру, получается то же самое.....

    а мне надо получить, даже не знаю как объяснить, если на пальцах, то "уровень смещения "вложенного массива" "для того, что бы правильно вывести дерево сообщений.
     
  22. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград

    через запятые я сам написал, если так проще то получаю 123...

    несколько значений, т.к. вычисления эти в цикле производятся
     
  23. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    тогда в чем бяда? =)
     
  24. Dmitriy A. Arteshuk

    Dmitriy A. Arteshuk Активный пользователь

    С нами с:
    19 янв 2012
    Сообщения:
    2.445
    Симпатии:
    66
    Адрес:
    Зеленоград
    Бяда в том
    Код (Text):
    1. Array
    2. (
    3.     [0] => Array
    4.         (
    5.             [id] => 15
    6.             [pid] => 0
    7.             [module_id] => comments1
    8.                 (
    9.                  [0] => Array
    10.                         (
    11.                             [id] => 16
    12.                             [pid] => 15
    13.                             [module_id] => comments1
    14.                          )
    15.                   [1] => Array
    16.                          (
    17.                             [id] => 21
    18.                             [pid] => 16
    19.                             [module_id] => comments1
    20.                          )
    21.                )
    22.         )
    23. )
    что для записи с id 21 я должен получить значение 2, а получаю 3...

    2 - это образно говоря 2 пробела, т.е. в итоге я должен вывести

    Код (Text):
    1. id15
    2.       id16
    3.       id21
    а не

    Код (Text):
    1. id15
    2.       id16
    3.             id21
     
  25. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    если хочешь увидеть мой вариант, то тогда тебе придется придумать название для того члена массива, в котором живут другие массивы.