gzhegow
@gzhegow
Думал, стану умнее, когда адаптируюсь, но нет

Почему код сортировки работает не так как ожидается?

Вот код, сортируется некое меню на PHP. Знаю, что это можно сделать прямо базой, но хочу понять как работает.

usort($menu, function ($a, $b) {
    return (0
      || ($a["level"] - $b["level"])
      || ($a["parent_id"] - $b["parent_id"])
      || ($a["id"] - $b["id"])
    );
  });


Я ожидаю что он возьмет два элемента, сравнит уровни. Если одинаковые, сравнит родителей, если родители - сравнит id.
Везде строго int числа.

Почему-то сортирует черти как, то есть нет такого что сначала идет раздел, потом подраздел, потом подподраздел, потом опять раздел, его подразделы и тд.
просто скорее всего бред написал, сама сортировка такая делается по другому принципу...
  • Вопрос задан
  • 210 просмотров
Решения вопроса 3
@Sayonji
В php вообще-то нельзя так пользоваться оператором ||, он всё приведет к типу bool и вы получите на выходе только 1 и 0. Так делают в джавасприкте, а в php нужно писать ?:
return $x1 - $y1 ?: ($x2 - $y2 ?: ($x3 - $y3));
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
Первый критерий, по которому сортируем,— уровень.
То есть, сначала корень, потом его потомки, потом потомки потомков…

Второй критерий — коды родителей. Точно вам надо сортировать по кодам, а не по текстам?

И третий — коды самих пунктов. Аналогично.

Итого. Будет сначала корень, потом его потомки по кодам, потом их потомки по паре «код предка → свой код», и т.д.
Ответ написан
gzhegow
@gzhegow Автор вопроса
Думал, стану умнее, когда адаптируюсь, но нет
ОБНОВЛЕНО 06.12.2016
sandbox.onlinephpfunctions.com/code/41ea9f04b0e9b2...

Внимание, функция tree() используется для вывода. В нашем случае мы получили массив, в случае вложенного меню, в ней нужно работать прямо с версткой, поскольку результирующий массив можно будет вывести в виде дерева на плоскости, с выводом одно-внутри-другого будут проблемы, поскольку это все одна коллекция.

<?php
error_reporting(0);

// эмуляция БД - если у вас SQL - это не нужно
$menu = array(
    array("id", "parent_id", "level"),
    
    array(1, 0, 0),
    array(2, 0, 0),
    array(3, 0, 0),
    array(4, 0, 0),
    array(5, 0, 0),
    array(6, 0, 0),
    array(7, 0, 0),
    array(8, 0, 0),
    array(9, 0, 0),
    array(10, 0, 0),
    array(11, 0, 0),
    
    array(17, 15, 1),
    array(18, 15, 1),
    array(19, 15, 1),
    array(20, 15, 1),
    array(21, 15, 1),
    array(22, 15, 1),
    array(23, 15, 1),
    array(17, 1, 2),
    array(18, 1, 2),
    array(19, 1, 2),
    array(20, 1, 2),
    array(21, 1, 2),
    array(22, 1, 2),
    array(23, 1, 2),
    
    array(24, 16, 1),
    array(25, 16, 1),
    array(26, 16, 1),
    array(27, 16, 1),
    array(28, 16, 1),
    array(24, 2, 2),
    array(25, 2, 2),
    array(26, 2, 2),
    array(27, 2, 2),
    array(28, 2, 2),    

    array(12, 1, 1),
    array(13, 1, 1),
    array(14, 1, 1),
    array(15, 1, 1),
    
    array(16, 2, 1),
);
$columns = array_shift($menu);
$menu = array_map(function ($v) use ($columns) {
    return array_combine($columns, array_replace(array_fill(0, count($columns), NULL), $v));
}, $menu);


// сортируем правильно - если у вас SQL - делайте в запросе
usort($menu, function ($a, $b) {
   return 0
    ?: ($a["level"] - $b["level"])
    ?: ($a["parent_id"] - $b["parent_id"])
    ?: ($a["id"] - $b["id"]);
});


// выбираем в массив по родителям
$menu_parents = array();
foreach ($menu as $v):
    $menu_parents[$v["parent_id"]][] = $v;
endforeach;


// пробегаем каждый элемент собирая потомки по очереди
function tree($arr, $parent_id = 0, &$res = array()) {
    foreach ($arr[$parent_id] as $v):
        $id = $v["id"];
        if (!isset($res[$id])):
            $res[$id] = $v;
        elseif ($res[$id]["level"] < $v["level"]):
            $res[$id] = $v;
        endif;
        if (isset($arr[$id])):
            tree($arr, $id, $res);
        endif;
    endforeach;
  return $res;
}
$menu = tree($menu_parents);


echo "<pre>";
print_r($menu);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Эвотор Москва
от 180 000 до 300 000 ₽
OnederX Москва
от 100 000 до 120 000 ₽
Технология Тюмень
от 50 000 до 130 000 ₽
08 авг. 2020, в 17:08
15000 руб./за проект
08 авг. 2020, в 16:12
10000 руб./за проект
08 авг. 2020, в 16:07
5000 руб./за проект