За последние 24 часа нас посетили 18408 программистов и 1605 роботов. Сейчас ищут 947 программистов ...

Сортировка многомерных массивов

Тема в разделе "PHP для новичков", создана пользователем IceCream, 23 апр 2012.

  1. IceCream

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

    С нами с:
    1 июл 2011
    Сообщения:
    27
    Симпатии:
    0
    Есть такой массив:
    Код (Text):
    1.  
    2. Array (
    3.     [0] => Array (
    4.         [0] => Главный каталог 1
    5.         [1] => Каталог второго уровня 1 главного каталога 1
    6.         [2] => Спорт
    7.     )
    8.     [1] => Array (
    9.         [0] => Главный каталог 1
    10.         [1] => Каталог второго уровня 2 главного каталога 1
    11.         [2] => Путешествия
    12.     )
    13.     [2] => Array (
    14.         [0] => Главный каталог 1
    15.         [1] => Каталог второго уровня 2 главного каталога 1
    16.         [2] => Погода
    17.     )
    18.     [3] => Array (
    19.         [0] => Главный каталог 2
    20.         [1] => Каталог второго уровня 1 главного каталога 2
    21.         [2] => Часы
    22.     )
    23.     [4] => Array (
    24.         [0] => Главный каталог 2
    25.         [1] => Каталог второго уровня 1 главного каталога 2
    26.         [2] => Монеты
    27.     )
    28. )
    Задача собрать меню вида
    Код (Text):
    1.  
    2. Главный каталог 1
    3.     Каталог второго уровня 1 главного каталога 1
    4.         Спорт
    5.     Каталог второго уровня 2 главного каталога 1
    6.         Путешествия
    7.         Погода
    8. Главный каталог 2
    9.     Каталог второго уровня 1 главного каталога 2
    10.         Часы
    11.         Монеты
    Подскажите куда копать?
     
  2. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    массив говно.

    Добавлено спустя 54 секунды:
    надо пересобрать, если можно. из такого массива ничего путного не выйдет.
     
  3. html-программист

    html-программист Активный пользователь

    С нами с:
    10 фев 2012
    Сообщения:
    831
    Симпатии:
    4
    Адрес:
    Kiev
    Да не, чего сразу говно? Нормальный такой массив. Только не понятно: названия каталогов есть, а ссылки где хранятся?
     
  4. IceCream

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

    С нами с:
    1 июл 2011
    Сообщения:
    27
    Симпатии:
    0
    В базе каталоги хранятся в виде:

    Главный каталог 1/Каталог второго уровня 1 главного каталога 1/Спорт/
    Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Путешествия/
    Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Погода/
    Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Часы/
    Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Монеты/

    как из этих исходных данных лучше сформировать меню?

    Может быть надо изменить алгоритм парсинга каталогов в базу как таковых?
    Например сделать отдельную таблицу где бы хранился каждый каталог с id родителя?
     
  5. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    первый массив - говно. потому что там всё не так =)

    как именно они хранятся в базе? вот прям такими строками? скажи точнее

    в любом случае это не сложно. доберусь до компа - подскажу. пока дай больше инфо.
     
  6. IceCream

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

    С нами с:
    1 июл 2011
    Сообщения:
    27
    Симпатии:
    0
    Прямо так, строками разделёнными обратным слешем, но у меня был вариант это переделать к виду:
    "сделать отдельную таблицу где бы хранился каждый каталог с id родителя"

    Первый массив собрал функцией explode() какраз из этих строк, была идея упорядочить выборку каталогов, потом сформировать этот массив. После пройтись по нему в цикле отбирая по принципу: записываем элемент с индексом 0, записываем элемент с индектом 1, записываем элемент с индексом 2. (и получаем первое дерево меню) В следующей интерации проверяем изменения элементов 0 и 1 и если их нет добавляем в первое дерево ещё один пункт в каталог второго уровня. Если изменения есть соответственно или создаём новое дерево или добавляем каталог второго уровня к существующему.
    Но в такой ситуации плохо понимаю как работать с разными по уровню вложенности каталогами...
     
  7. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    не, это разу надо делать.

    их всегда так: один каталог, один подкаталог, и раздел? Всегда три элемента? всегда два слеша?
     
  8. IceCream

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

    С нами с:
    1 июл 2011
    Сообщения:
    27
    Симпатии:
    0
    Нет по разному, от одного до 5ти.
    Слэш ещё в конце есть, но я его выпиливал перед формированием массива за ненадобностью.
     
  9. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    это пофик.
    но ща не смогу помочь. может вечером, может завтра.
     
  10. IceCream

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

    С нами с:
    1 июл 2011
    Сообщения:
    27
    Симпатии:
    0
    Буду очень благодарен!
     
  11. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    у меня не получилось пока =) оказалось сложнее, чем я думал.
     
  12. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Нужно, чтобы папки (раделы) были как-то представлены, чтобы у них был свой id в БД. Тогда можно строить иерархию.
    А просто вывести в виде деревца, так я сделал, но нужно ли? Как ссылки делать, по каким id ориентироваться? Или тут id - это порядковый номер записи?
     
  13. html-программист

    html-программист Активный пользователь

    С нами с:
    10 фев 2012
    Сообщения:
    831
    Симпатии:
    4
    Адрес:
    Kiev
    тут ЧПУ походу. Ссылки без id
     
  14. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    покаж плс
     
  15. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Код (PHP):
    1. $instr=
    2. 'Главный каталог 1/Каталог второго уровня 1 главного каталога 1/Спорт/
    3. Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Путешествия/
    4. Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Погода/
    5. Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Часы/
    6. Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Монеты/';
    7.  
    8. $tArr=explode("\n", $instr);
    9. $menu=array();//тут иерархия
    10. $counter=0;//можно с 1 начать, если в базе id начинается с 1
    11. foreach($tArr as $line){
    12.     $line=trim($line,'/');//по краям убираем слеш
    13.     $tempArr=explode('/', $line);//временный массив из строки
    14.     $key1=array_shift($tempArr);//ключ для 1 уровня
    15.     $key2=array_shift($tempArr);//ключ для 2 уровня
    16.     $key3=array_shift($tempArr);//ключ для 3 уровня
    17.     
    18.     if(!isset($menu[$key1])){
    19.         $menu[$key1]=array();
    20.     }
    21.     if(!isset($menu[$key1][$key2])){
    22.         $menu[$key1][$key2]=array();
    23.     }
    24.     if(!isset($menu[$key1][$key2][$key3])){
    25.         $menu[$key1][$key2][$key3]=array();
    26.     }
    27.     $menu[$key1][$key2][$key3]=$counter;
    28.     $counter+=1;
    29. }
    30. //echo '<pre>';
    31. //print_r($menu);
    32. //echo '</pre>';
    33.  
    34. //выводим меню
    35. function tree(&$arr,$lvl=0){
    36.     $lvl++;
    37.     if(is_array($arr)){
    38.         echo "\n",str_repeat("\t",$lvl),'<ul>',"\n";
    39.         foreach($arr as $key=>$branch){
    40.             $isArray=is_array($branch);
    41.             if(!$isArray){
    42.                 echo str_repeat("\t",$lvl),'<li><a href="?id='.$branch.'">',$key;
    43.             }else{
    44.                 echo str_repeat("\t",$lvl),'<li>',$key;
    45.             }
    46.             tree($branch,$lvl);
    47.             if(!$isArray){
    48.                 echo '</a></li>',"\n";
    49.             }else{
    50.                 echo '</li>',"\n";
    51.             }
    52.         }
    53.         echo str_repeat("\t",$lvl),'</ul>',"\n";
    54.     }
    55.     $lvl--;
    56. }
    57.  
    58. tree($menu); 
    Добавлено спустя 1 минуту 5 секунд:
    Но всё это не правильно, т.к. теперь в тексте нельзя хранить слэш, чтобы не нарушить структуру.
     
  16. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    до пяти можно и так, конечно.

    я пытался задрочить рекурсию, но чета нифига не понял. вобще.
     
  17. YSandro

    YSandro Старожил

    С нами с:
    7 апр 2011
    Сообщения:
    2.523
    Симпатии:
    2
    Уже тут увидел, можно оптимизировать внутри функции, меньше проверок делать.
    Во, так покрасивей
    Код (PHP):
    1. $instr=
    2. 'Главный каталог 1/Каталог второго уровня 1 главного каталога 1/Спорт/
    3. Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Путешествия/
    4. Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Погода/
    5. Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Часы/
    6. Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Монеты/';
    7.  
    8. $tArr=explode("\n", $instr);
    9. $menu=array();//тут иерархия
    10. $counter=0;//можно с 1 начать, если в базе id начинается с 1
    11. foreach($tArr as $line){
    12.     $line=trim($line,'/');//по краям убираем слеш
    13.     $tempArr=explode('/', $line);//временный массив из строки
    14.     $key1=array_shift($tempArr);//ключ для 1 уровня
    15.     $key2=array_shift($tempArr);//ключ для 2 уровня
    16.     $key3=array_shift($tempArr);//ключ для 3 уровня
    17.     
    18.     if(!isset($menu[$key1])){
    19.         $menu[$key1]=array();
    20.     }
    21.     if(!isset($menu[$key1][$key2])){
    22.         $menu[$key1][$key2]=array();
    23.     }
    24.     if(!isset($menu[$key1][$key2][$key3])){
    25.         $menu[$key1][$key2][$key3]=array();
    26.     }
    27.     $menu[$key1][$key2][$key3]=$counter;
    28.     $counter+=1;
    29. }
    30.  
    31. //выводим меню
    32. function tree(&$arr,$lvl=0){
    33.     $lvl++;
    34.     if(is_array($arr)){
    35.         echo "\n",str_repeat("\t",$lvl-1),'<ul>',"\n";
    36.         foreach($arr as $key=>$branch){
    37.             $isArray=is_array($branch);
    38.             if($isArray){
    39.                 echo str_repeat("\t",$lvl),'<li>',$key;
    40.                 tree($branch,$lvl);
    41.                 echo str_repeat("\t",$lvl),'</li>',"\n";
    42.             }else{
    43.                 echo sprintf('%s<li>[url="?id=%d"]%s[/url]</li>%s',str_repeat("\t",$lvl),$branch,$key,"\n");
    44.             }
    45.         }
    46.         echo str_repeat("\t",$lvl-1),'</ul>',"\n";
    47.     }
    48.     $lvl--;
    49. }
    50.  
    51. tree($menu); 
     
  18. igordata

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

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

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

    С нами с:
    1 июл 2011
    Сообщения:
    27
    Симпатии:
    0
    Спасибо за ответы!
    Вообще ID в базе есть.
    Вот что есть:
    id - Собственно уникальный идентификатор записи. Генерятся автоматически когда добавляется новый каталог. Новый каталог добавляется при импорте прайс листа, если парсер разбирая csv файл не нашёл совпадений в базе. Точнее так, каталог создаётся и его id помещается в соответсвующее поле таблицы с товарами. Если же парсер нашё совпадение, то он берёт ID совпавшего поля и проделывает уже с ним описанное ранее.
    price - К какому прайс листу принадрежит запись. Так как записи выгружаются из разных прайс листов соответственно существует база с их перечнем идентификатором, заголовком описанием и прочими вещами. Это по сути линк на соответствующее поле в той таблице.
    catalogs - Вот тут и хранится текст вида "Главный каталог 1/Каталог второго уровня 1 главного каталога 1/Спорт/". Текст состоит только из пробелов и символов литиницы и кириллицы, разбитых обратными слешами по уровню вложенности, никаких спецсимволов тут быть не может.
    time - время создания/изменения записи
     
  20. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Дай угодаю, ты наверно был с похмелья? :D
    По себе заметил, что с похмелья рекурсивный обход всяких там parent_id даётся трудновато... В последний раз совсем недавно сталкивался с этим, утром еле встал после вечерней попойки, наверно часа 4 никак не мог сообразить как это делается (через 4 часа, видимо наступило отрезвление) :)))

    По теме - нужно, конечно, вникать в конкретную задачу, как там всё работает, но на первый взгляд мне кажется, что структура б.д. должна быть несколько другой. Думаю, для каталогов должна быть отдельная таблица...