Я хочу отсортировать массив древовидной иерархии со структурой, как показано ниже, на основе ключа (в этом примере: отметка времени).
$topics = array(
array('name' => 'n1', 'timestamp' => 5000, 'children' => array()),
array('name' => 'n2', 'timestamp' => 4000, 'children' => array(
array('name' => 'n3', 'timestamp' => 6000, 'children' => array()),
array('name' => 'n4', 'timestamp' => 2000, 'children' => array(
array('name' => 'n5', 'timestamp' => 4000, 'children' => array()),
array('name' => 'n6', 'timestamp' => 3000, 'children' => array())
)),
)),
array('name' => 'n7', 'timestamp' => 1000, 'children' => array())
);
Моя функция сортировки:
function sequenceSort(&$a, &$b) {
if (!empty($a['children'])) {
usort($a['children'], 'sequenceSort');
}
if ($a['timestamp'] == $b['timestamp']) {
return 0;
}
return $a['timestamp'] < $b['timestamp'] ? -1 : 1;
}
usort($topics, 'sequenceSort');
print_a($topics);
На некоторых уровнях он дает правильный результат, на другом - нет, например:
1000 ✔
4000 ✔
6000 ✘
2000 ✘
4000 ✘
3000 ✘
5000 ✔
Что в этом плохого?
@kaspars Для этого я использую передачу по ссылкам.
Обратите внимание, что вы должны упорядочить свой входной массив по-другому, чтобы увидеть, действительно ли он сортируется. Второй уровень теперь также не работает, но вы этого не видите, потому что вы уже правильно его отсортировали.
@jeroen Я отредактировал вопрос с более случайным порядком ввода.
@emix Должно быть <=> (single =), верно?






Это не работает, потому что usort() не передает элементы массива по ссылке, даже если вы объявили параметры с помощью &. Я добавил:
$a['touched'] = true;
в функцию сравнения, и когда я распечатал результат, этих ключей нигде не было.
Однако, даже если это сработало, это кажется очень плохим способом сделать это, поскольку он будет сортировать дочерние элементы несколько раз - каждый раз, когда родитель сравнивается с другим родителем, ему придется пересортировать дочерние элементы, и внуки и т. д.
Было бы лучше написать рекурсивную функцию, которая сортирует один уровень, затем выполняет итерацию по дочерним элементам и так далее.
function sortRecurse(&$array) {
usort($array, function($a, $b) {
return $a['timestamp'] - $b['timestamp'];
});
foreach ($array as &$subarray) {
sortRecurse($subarray['children']);
}
}
Я так и думал, но это тоже неправильно.
@JustinusHermawan Это не работает, потому что элементы не передаются по ссылке в функцию сравнения. Так что приведенный выше комментарий Каспара верен.
@barmar Да, работает. Итак, ошибка здесь в том, что функция usort() не извлекает параметры по ссылке, верно?
Он получает свой собственный параметр по ссылке, но не передает параметры в функцию сравнения по ссылке.
так плохо, я опоздал sandbox.onlinephpfunctions.com/code/…
Не назначайте $topics[$i][]. recSort() модифицирует массив на месте, ничего не возвращает.
Вы не можете изменить массив внутри
usort