Сортировка многомерного массива php по полю. Операции с массивами
(PHP 4, PHP 5, PHP 7)
array_multisort — Сортирует несколько массивов или многомерные массивы
Описание
Функция array_multisort() может быть использована для сортировки сразу нескольких массивов или одного многомерного массива в соответствии с одной или несколькими размерностями.
Array1_sort_order
Порядок для сортировки вышеуказанного аргумента array . Или SORT_ASC для сортировки по возрастанию, или SORT_DESC для сортировки по убыванию.
Этот аргумент может меняться местами с array1_sort_flags или вообще быть пропущенным. В этом случае подразумевается значение SORT_ASC .
Array1_sort_flags
Настройки сортировки для вышеуказанного аргумента array :
Флаг способа сортировки:
- SORT_REGULAR - обычное сравнение элементов (без изменения типов)
- SORT_NUMERIC - сравнение элементов как чисел
- SORT_STRING - сравнение элементов как строк
- SORT_LOCALE_STRING - сравнение элементов как строк, учитывая текущую локаль. Используется локаль, которую можно менять с помощью функции setlocale()
- SORT_NATURAL - сравнение элементов как строк с использованием алгоритма "natural order", так же как в функции natsort()
- SORT_FLAG_CASE - может быть объединен (бинарное OR) с SORT_STRING или SORT_NATURAL для сортировки без учета регистра
Этот аргумент может меняться местами с array1_sort_order или вообще быть пропущенным. В этом случае подразумевается значение SORT_REGULAR .
...Дополнительные массивы, необязательно следующие после порядка сортировки и флагов.
Возвращаемые значения
Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки.
Список изменений
Примеры
Пример #1 Сортировка нескольких массивов
$ar1
= array(10
,
100
,
100
,
0
);
$ar2
= array(1
,
3
,
2
,
4
);
array_multisort
($ar1
,
$ar2
);
Var_dump
($ar1
);
var_dump
($ar2
);
?>
В вышеприведенном примере, после того, как будет осуществлена сортировка, первый массив будет содержать 0, 10, 100, 100. Второй - 4, 1, 2, 3. Элементы второго массива, соответствующие идентичным элементам первого (100 и 100), также будут отсортированы.
array(4) { => int(0) => int(10) => int(100) => int(100) } array(4) { => int(4) => int(1) => int(2) => int(3) }
Пример #2 Сортировка многомерного массива
$ar
= array(
array("10"
,
11
,
100
,
100
,
"a"
),
array(1
,
2
,
"2"
,
3
,
1
)
);
array_multisort
($ar
[
0
],
SORT_ASC
,
SORT_STRING
,
$ar
[
1
],
SORT_NUMERIC
,
SORT_DESC
);
var_dump
($ar
);
?>
В вышеприведенном примере, после сортировки, первый массив будет содержать "10", 100, 100, 11, "a" (его элементы были отсортированы в возрастающем порядке), а второй массив будет содержать 1, 3, "2", 2, 1 (элементы отсортированы как числа, в порядке убывания).
array(2) { => array(5) { => string(2) "10" => int(100) => int(100) => int(11) => string(1) "a" } => array(5) { => int(1) => int(3) => string(1) "2" => int(2) => int(1) } }
Пример #3 Сортировка результатов из базы данных
В этом примере, каждый элемент массива data представляет собой ряд таблицы. Такой тип данных типичен для записей базы данных.
Примерные данные:
# том | издание volume | edition -------+-------- 67 | 2 86 | 1 85 | 6 98 | 2 86 | 6 67 | 7
Данные представлены в виде массива с именем data . Обычно их можно получить, к пример, с помощью цикла из функции mysql_fetch_assoc() .
$data
= array("volume"
=>
67
,
"edition"
=>
2
);
$data
= array("volume"
=>
86
,
"edition"
=>
1
);
$data
= array("volume"
=>
85
,
"edition"
=>
6
);
$data
= array("volume"
=>
98
,
"edition"
=>
2
);
$data
= array("volume"
=>
86
,
"edition"
=>
6
);
$data
= array("volume"
=>
67
,
"edition"
=>
7
);
?>
В нашем примере мы будем сортировать по volume в убывающем порядке, а по edition - в возрастающем.
У нас есть массив строк, но array_multisort() необходим массив столбцов, поэтому сначала мы используем следующий код для получения столбцов, а потом выполним сортировку.
// Получение списка столбцов
foreach ($data
as
$key
=>
$row
) {
$volume
[
$key
] =
$row
[
"volume"
];
$edition
[
$key
] =
$row
[
"edition"
];
}
// Сортируем данные по volume по убыванию и по edition по возрастанию
// Добавляем $data в качестве последнего параметра, для сортировки по общему ключу
array_multisort
($volume
,
SORT_DESC
,
$edition
,
SORT_ASC
,
$data
);
?>
Я хотел бы добавить свое собственное решение здесь, так как оно предлагает функции, которые другие ответы не имеют.
В частности, преимущества этого решения включают:
- Он многоразовый : вы указываете столбец сортировки как переменную, а не hardcoding.
- гибкий : вы можете указать несколько столбцов сортировки (сколько угодно) - дополнительные столбцы используются в качестве разделителей между элементами, которые первоначально сравнивают одинаковые.
- обратимый : вы можете указать, что сортировка должна быть отменена - индивидуально для каждого столбца.
- расширяемый : если в наборе данных содержатся столбцы, которые не могут быть сопоставлены "немым" способом (например, строками даты), вы также можете указать, как преобразовать эти элементы в значение, которое может быть напрямую (например, экземпляр DateTime).
- ассоциативно, если вы хотите : этот код выполняет сортировку элементов, но вы выбираете фактическую функцию сортировки (usort или uasort).
- Наконец, он не использует array_multisort: в то время как array_multisort удобно, это зависит от создания проекции всех ваших входных данных перед сортировкой. Это потребляет время и память и может быть просто запретительным, если ваш набор данных большой.
Код
function make_comparer() { // Normalize criteria up front so that the comparer finds everything tidy $criteria = func_get_args(); foreach ($criteria as $index => $criterion) { $criteria[$index] = is_array($criterion) ? array_pad($criterion, 3, null) : array($criterion, SORT_ASC, null); } return function($first, $second) use (&$criteria) { foreach ($criteria as $criterion) { // How will we compare this round? list($column, $sortOrder, $projection) = $criterion; $sortOrder = $sortOrder === SORT_DESC ? -1: 1; // If a projection was defined project the values now if ($projection) { $lhs = call_user_func($projection, $first[$column]); $rhs = call_user_func($projection, $second[$column]); } else { $lhs = $first[$column]; $rhs = $second[$column]; } // Do the actual comparison; do not return if equal if ($lhs < $rhs) { return -1 * $sortOrder; } else if ($lhs > $rhs) { return 1 * $sortOrder; } } return 0; // tiebreakers exhausted, so $first == $second }; }Как использовать
$data = array(array("zz", "name" => "Jack", "number" => 22, "birthday" => "12/03/1980"), array("xx", "name" => "Adam", "number" => 16, "birthday" => "01/12/1979"), array("aa", "name" => "Paul", "number" => 16, "birthday" => "03/11/1987"), array("cc", "name" => "Helen", "number" => 44, "birthday" => "24/06/1967"),);
Основы
Функция make_comparer принимает переменное количество аргументов, которые определяют нужный тип, и возвращает функцию, которую вы должны использовать в качестве аргумента для usort или uasort .
Простейшим вариантом использования является передача ключа, который вы хотите использовать для сравнения элементов данных. Например, чтобы отсортировать $data с помощью элемента name , который вы делаете
Usort($data, make_comparer("name"));
Ключ может также быть числом, если элементы представляют собой числовые индексированные массивы. Для примера в вопросе это будет
Usort($data, make_comparer(0)); // 0 = first numerically indexed column
Несколько столбцов сортировки
Вы можете указать несколько столбцов сортировки, передав дополнительные параметры make_comparer . Например, для сортировки по "числу", а затем по столбцу с нулевой индексацией:
Usort($data, make_comparer("number", 0));
Расширенные функции
Дополнительные функции доступны, если вы укажете столбец сортировки как массив вместо простой строки. Этот массив должен быть численно проиндексирован и должен содержать следующие элементы:
0 => the column name to sort on (mandatory) 1 => either SORT_ASC or SORT_DESC (optional) 2 => a projection function (optional)
Посмотрим, как мы можем использовать эти функции.
Обратный сортировка
Сортировка по имени по убыванию:
Usort($data, make_comparer(["name", SORT_DESC]));
Для сортировки по убыванию номера, а затем по имени:
Usort($data, make_comparer(["number", SORT_DESC], ["name", SORT_DESC]));
Пользовательские прогнозы
В некоторых сценариях вам может понадобиться сортировать по столбцу, значения которого не позволяют хорошо сортировать. Столбец "День рождения" в наборе образцов данных соответствует этому описанию: нет смысла сравнивать дни рождения как строки (потому что "01/01/1980" предшествует "10/10/1970"). В этом случае мы хотим указать, как проецировать фактические данные в форму, которую можно напрямую сравнивать с желаемой семантикой.
Проекции могут быть указаны как любой тип callable : как строки, массивы или анонимные функции. Предполагается, что проекция принимает один аргумент и возвращает его проецируемую форму.
Следует отметить, что в то время как прогнозы похожи на пользовательские функции сравнения, используемые с usort и семейством, они проще (вам нужно только преобразовать одно значение в другое) и использовать все функции, уже запеченные в make_comparer .
Позвольте отсортировать набор данных примера без проекции и посмотреть, что произойдет:
Usort($data, make_comparer("birthday"));
Это не был желаемый результат. Но мы можем использовать date_create в качестве проекции:
Usort($data, make_comparer(["birthday", SORT_ASC, "date_create"]));
Это правильный порядок, который мы хотели.
Есть много других вещей, которые могут достичь прогнозы. Например, быстрый способ получить регистр без учета регистра - использовать strtolower в качестве проекции.
Тем не менее, я должен также упомянуть, что лучше не использовать прогнозы, если ваш набор данных велик: в этом случае было бы намного быстрее проецировать все ваши данные вручную, а затем сортировать, не используя проекцию, хотя делать поэтому будет увеличивать использование памяти для более быстрой скорости сортировки.
Наконец, вот пример, который использует все функции: он сначала сортируется по убыванию числа, а по возрастанию по дням:
Usort($data, make_comparer(["number", SORT_DESC], ["birthday", SORT_ASC, "date_create"]));
3.5KБлагодаря своей мощности и гибкости в работе массивы стали непременным атрибутом PHP . Причем, в ряде сложных ситуаций можно задействовать и двумерные массивы PHP . Данная статья посвящена сортировке многомерных массивов в PHP .
Составляющие :
- Многомерный массив;
- Встроенные функции PHP usort () , uasort () или uksort () ;
- Встроенные функции PHP strcasecmp() или strcmp() .
Реализация
:
Допустим что, у нас есть массив:
$students = array (1 => array ("name" => "Jack", "grade" => 98.5), 2 => array ("name" => "Bill", "grade" => 90.1), 3 => array ("name" => "Chloe", "grade" => 94.0), 4 => array ("name" => "Taylor", "grade" => 95.1), 5 => array ("name" => "Larry", "grade" => 94.6));
Здесь можно осуществить сортировку двумерного массива PHP по параметру grade (оценка ) (числовая сортировка ) или name (имя ) (сортировка в алфавитном порядке ).
Внешний массив $students состоит из пяти элементов, каждый из которых также представлен в виде отдельного массива. Внутренний массив использует ID студента в качестве ключа и хранит два значения: имя студента и его оценку.
Для сортировки многомерного массива мы задаем собственную функцию. Говорим PHP , что именно ее нужно использовать для вызова встроенных функций usort () , uasort () или uksort () .
Определяемая функция должна принимать два параметра и возвращать значение, указывающее, какой именно параметр идет первым по списку. Отрицательное или false значение говорит о том, что первый параметр указывается до второго. Положительное или true — что вначале идет второй параметр. Нулевое значение (0 ) указывает, что оба параметра равнозначны.
A – Сортировка по оценке (параметр grade) (числовая сортировка)
Определим функцию для сортировки массива по оценке (параметр grade ):
// Функция сортировки по оценке: сортировка по УБЫВАНИЮ. function grade_sort($x, $y) { if ($x[" оценка "] < $y[" оценка "]) { return true; } else if ($x["оценка"] > $y["оценка"]) { return false; } else { return 0; } }
Затем возьмем пользовательскую функцию и осуществим перебор двумерного массива PHP по первому ключу. Выглядит это примерно так:
// $students – наш многомерный массив, а grade_sort – созданная функция usort ($students, " grade_sort ");
Пример :
// Вызвать на печать массив в виде (начальный массив): echo "
Массив в виде
" . print_r($students, 1) . ""; // Сортировать по оценке (grade): uasort($students, "grade_sort"); echo "
Массив отсортирован по оценке
" . print_r($students, 1) . "";
PHP будет отправлять внутренние массивы к этой функции для дальнейшей сортировки. Если вам интересно, как все это происходит в деталях, то выведите на экран результаты сравнения значений внутри функции. А саму функцию после PHP создания двумерного массива измените следующим образом:
function grade_sort($x, $y) { static $count = 1; echo “
Iteration $count: {$x[‘оценка’]} vs. {$y[‘оценка’]}
n”; $count++; if ($x[‘ оценка ‘] < $y[‘ оценка ‘]) { return true; } else if ($x[‘ключ1′] > $y[‘ключ1′]) { return false; } else { return 0; } }Выводя на экран значения $x[‘оценка’] и $y [‘оценка’] , можно увидеть, как вызывается функция сортировки, определенная пользователем.
Можно сократить функцию grade_sort следующим образом:
// Функция числовой сортировки по оценке: сортировка по УБЫВАНИЮ function grade_sort($x, $y) { return ($x["grade"] < $y["grade"]); }
Результаты сортировки двумерного массива PHP по оценке отображены на картинке ниже:
Примечание : Функция usort () сортирует по значениям, но не сохраняет ключи (для внешнего массива ). Если ключи нужны, то лучше использовать функцию uasort () .
B – Сортировка по имени (в алфавитном порядке)
Чтобы отсортировать массив $students по первому ключу, необходимо сравнить две строки. Поэтому в примере с сортировкой в алфавитном порядке воспользуемся функция strcasecmp() (не чувствительна к регистру ) и strcmp() (чувствительна к регистру ). Получившийся двумерный массив PHP будет иметь следующий вид.
Последнее обновление: 1.11.2015
Функция is_array
Функция is_array() проверяет, является ли переменная массивом, и если является, то возвращает true , иначе возвращает false . Например:
$isar = is_array($technics); echo ($isar==true)?"это массив":"это не массив";
Функции count/sizeof
Функция count() и sizeof() получают количество элементов массива:
$number = count($technics); // то же самое, что // $number = sizeof($technics); echo "В массиве technics $number элементов";
Функции shuffle
Функция shuffle перемешивает элементы массивы случайным образом:
$os = array("Windows 95", "Windows XP", "Windows Vista", "Windows 7", "Windows 8", "Windows 10"); shuffle($os); print_r($os); // один из возможных вариантов // Array ( => Windows 95 => Windows 7 => Windows Vista => Windows XP => Windows 10 => Windows 8)
Функции compact
Функция compact позволяет создать из набора переменных ассоциативный массив, где ключами будут сами имена переменных:
Apple II => Apple => 1978) ?>
Функция compact получает в скобках набор переменных. Каждая переменная указывается в кавычка без знака $. Результатом функции является новый массив.
Сортировка массивов
В PHP имеются два типа сортировки: сортировка строк по алфавиту и сортировка чисел по возрастанию/убыванию. Если сортируемые значения представляют строки, то они сортируются по алфавиту, если числа - то они сортируются в порядке возрастания чисел. PHP по умолчанию самостоятельно выбирает тип сортировки.
Для сортировки по возрастанию используется функция asort :
"Lenovo IdeaTab A3500", "samsung" => "Samsung Galaxy Tab 4", "apple" => "Apple iPad Air"); asort($tablets); echo "
- ";
foreach ($tablets as $key => $value)
{
echo "
- $key: $value "; } echo "
В данном случае значения массива представляют строки, поэтому PHP выберет сортировку по алфавиту. Однако с помощью дополнительного параметра мы можем явно указать интерпретатору PHP тип сортировки. Данный параметр может принимать три значения:
SORT_REGULAR: автоматический выбор сортировки
SORT_NUMERIC: числовая сортировка
SORT_STRING: сортировка по алфавиту
Укажем явно тип сортировки:
Asort($tablets, SORT_STRING);
Чтобы отсортировать массив в обратном порядке, применяется функция arsort :
Arsort($tablets);
Сортировка по ключам
Функция asort производит сортировку по значениям элементов, но также существует и еще и сортировка по ключам. Она представлена функцией ksort :
Ksort($tablets, SORT_STRING);
Сортировка по ключам в обратном порядке выполняется функцией krsort() :
Krsort($tablets);
Естественная сортировка
Хотя выше описанные функции сортировки прекрасно выполняют свою работу, но их возможностей все-таки недостаточно. Например, отсортируем по возрастанию следующий массив:
Windows 10 => Windows 7 => Windows 8) ?>
Так как значения представляют строки, то PHP сортирует по алфавиту. Однако подобная сортировка не учитывает числа и регистр. Поэтому значение "Windows 10" будет идти в самом начале, а не в конце, как должно было быть. И для решения этой проблемы в PHP есть функция natsort() , которая выполняет естественную сортировку:
Windows 7 => Windows 8 => Windows 10) ?>
Если нам надо еще при этом, чтобы сортировка не учитывала регистр, то мы можем применить функцию natcasesort() .