Базовые одномерные массивы
$array = array(3, 5, 2, 8);
Применимые функции сортировки:
sort
rsort
asort
arsort
natsort
natcasesort
ksort
krsort
Разница между ними заключается только в том, сохраняются ли ассоциации "ключ-значение" (функции a
), сортируются ли они по возрастанию или наоборот (r
), сортируются ли значения или ключи (k
) и как сравниваются значения (nat
vs . обычный). См. http://php.net/manual/en/array.sorting.php для обзора и ссылок на более подробную информацию.
Многомерные массивы, включая массивы объектов
$array = array(
array('foo' => 'bar', 'baz' => 42),
array('foo' => ..., 'baz' => ...),
...
);
Если вы хотите отсортировать $array
по ключу 'foo' каждой записи, вам понадобится настраиваемая функция сравнения. Вышеупомянутые sort
и связанные функции работают с простыми значениями, которые они умеют сравнивать и сортировать. PHP не просто знает, что делать с сложным значением, например array('foo' => 'bar', 'baz' => 42)
; так что тебе нужно это сказать.
Для этого вам нужно создать функцию сравнения. Эта функция принимает два элемента и должна возвращать 0
, если эти элементы считаются равными, значение ниже 0
, если первое значение ниже, и значение выше 0
, если первое значение выше. Вот и все, что нужно:
function cmp(array $a, array $b) {
if ($a['foo'] < $b['foo']) {
return -1;
} else if ($a['foo'] > $b['foo']) {
return 1;
} else {
return 0;
}
}
Часто вам может понадобиться использовать анонимную функцию в качестве обратного вызова. Если вы хотите использовать метод или статический метод, см. другие способы указания обратного вызова в PHP.
Затем вы используете одну из этих функций:
Опять же, они различаются только тем, сохраняют ли они ассоциации «ключ-значение» и сортируют по значениям или ключам. Подробности читайте в их документации.
Пример использования:
usort($array, 'cmp');
usort
возьмет два элемента из массива и вызовет с ними вашу cmp
функцию. Таким образом, cmp()
будет вызываться с $a
как array('foo' => 'bar', 'baz' => 42)
и $b
как еще array('foo' => ..., 'baz' => ...)
. Затем функция возвращается к usort
, какое из значений было больше или были ли они равны. usort
повторяет этот процесс, передавая разные значения для $a
и $b
, пока массив не будет отсортирован. Функция cmp
будет вызываться много раз, по крайней мере столько раз, сколько есть значений в $array
, с разными комбинациями значений для $a
и $b
каждый раз.
Чтобы привыкнуть к этой идее, попробуйте следующее:
function cmp($a, $b) {
echo 'cmp called with $a:', PHP_EOL;
var_dump($a);
echo 'and $b:', PHP_EOL;
var_dump($b);
}
Все, что вы сделали, это определили собственный способ сравнения двух элементов, это все, что вам нужно. Это работает со всеми видами ценностей.
Кстати, это работает с любым значением, значения не обязательно должны быть сложными массивами. Если у вас есть собственное сравнение, которое вы хотите провести, вы также можете сделать это с простым массивом чисел.
sort
сортирует по ссылке и не возвращает ничего полезного!
Обратите внимание, что массив сортируется на месте, вам не нужно назначать возвращаемое значение чему-либо. $array = sort($array)
заменит массив на true
, а не на отсортированный массив. Просто sort($array);
работает.
Пользовательские числовые сравнения
Если вы хотите выполнить сортировку по клавише baz
, которая является числовой, все, что вам нужно сделать, это:
function cmp(array $a, array $b) {
return $a['baz'] - $b['baz'];
}
Благодаря PoWEr OF MATH это возвращает значение ‹0, 0 или› 0 в зависимости от того, является ли $a
меньше, равно или больше $b
.
Обратите внимание, что это не сработает для значений float
, поскольку они будут уменьшены до int
и потеряют точность. Вместо этого используйте явные возвращаемые значения -1
, 0
и 1
.
Объекты
Если у вас есть массив объектов, он работает так же:
function cmp($a, $b) {
return $a->baz - $b->baz;
}
Функции
Вы можете делать все, что вам нужно, внутри функции сравнения, включая функции вызова:
function cmp(array $a, array $b) {
return someFunction($a['baz']) - someFunction($b['baz']);
}
Струны
Ярлык для первой версии сравнения строк:
function cmp(array $a, array $b) {
return strcmp($a['foo'], $b['foo']);
}
strcmp
выполняет в точности то, что ожидается от cmp
, возвращает -1
, 0
или 1
.
Оператор космического корабля
В PHP 7 появился оператор космического корабля, который унифицирует и упрощает сравнение типов: равно / меньше / больше, чем:
function cmp(array $a, array $b) {
return $a['foo'] <=> $b['foo'];
}
Сортировка по нескольким полям
Если вы хотите сортировать в первую очередь по foo
, но если foo
равно для двух элементов, выполните сортировку по baz
:
function cmp(array $a, array $b) {
if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) {
return $cmp;
} else {
return $a['baz'] - $b['baz'];
}
}
Для тех, кто знаком, это эквивалентно SQL-запросу с ORDER BY foo, baz
.
Также см. эту очень удобную сокращенную версию и как создать такую функцию сравнения динамически для произвольного количества ключей.
Сортировка в ручном статическом порядке
Если вы хотите отсортировать элементы в ручном порядке, например foo, bar, baz:
function cmp(array $a, array $b) {
static $order = array('foo', 'bar', 'baz');
return array_search($a['foo'], $order) - array_search($b['foo'], $order);
}
Для всего вышеперечисленного, если вы используете PHP 5.3 или выше (и вам действительно следует), используйте анонимные функции для более короткого кода и во избежание появления другой глобальной функции, плавающей вокруг:
usort($array, function (array $a, array $b) { return $a['baz'] - $b['baz']; });
Вот насколько простой может быть сортировка сложного многомерного массива. Опять же, просто подумайте о том, чтобы научить PHP определять, какой из двух элементов лучше; пусть PHP выполняет фактическую сортировку.
Также для всего вышеперечисленного, чтобы переключаться между возрастающим и убывающим порядком, просто поменяйте местами аргументы $a
и $b
. Например.:
return $a['baz'] - $b['baz']; // ascending
return $b['baz'] - $a['baz']; // descending
Сортировка одного массива по другому
А еще есть своеобразный array_multisort
, который позволяет сортировать один массив на основе другого:
$array1 = array( 4, 6, 1);
$array2 = array('a', 'b', 'c');
Ожидаемый результат здесь будет:
$array2 = array('c', 'a', 'b'); // the sorted order of $array1
Используйте array_multisort
, чтобы попасть туда:
array_multisort($array1, $array2);
Начиная с PHP 5.5.0 вы можете использовать array_column
для извлечения столбца из многомерного массива и сортировки массива по этому столбцу:
array_multisort(array_column($array, 'foo'), SORT_DESC, $array);
Вы также можете сортировать более чем по одному столбцу в каждом направлении:
array_multisort(array_column($array, 'foo'), SORT_DESC,
array_column($array, 'bar'), SORT_ASC,
$array);
Начиная с PHP 7.0.0, вы также можете извлекать свойства из массива объектов.
Если у вас есть более частые случаи, не стесняйтесь редактировать этот ответ.
person
deceze♦
schedule
28.06.2013