Определенную информацию всегда легче получать из отсортированных данных, в обратном случае вам приходится пересматривать по очереди каждый элемент массива. Например, предположим, что вы храните оценки разных учеников одного класса в массиве или таблице.  Если данные не отсортированы по оценкам, вам нужно пересмотреть оценку каждого учащегося, чтобы определить, кто получил самую высокую или или самую низкую. Если данные уже отсортированы от самой низкой к более высокой, то просто взглянув на оценку первого ученика, вы будете знать этот показатель.

Сортировка делает много простых и еффективных задач на основе доступа или получения определенного набора данных. В этом уроке мы узнаем, как использовать встроенные функции PHP для сортировки различных типов массивов.

Сортировка массива по значению

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

Для сортировки значений массива от низкого к высокому вы можете использовать функцию sort(&$array, $sort_flags). Однако, при сортировке массива он не будет поддерживать никаких ассоциаций ключевых значений.  Вместо простой перестановки новые ключи назначаются отсортированным элементам. Необязательный второй параметр указывает порядок сортировки элементов и может иметь шесть разных значений:

  1. SORT_REGULAR — сортировка значений без изменения их типов.
  2. SORT_NUMERIC — сортировка значений путем их численного сравнения.
  3. SORT_STRING — сортировка значений, сравнивая их как стринги.
  4. SORT_LOCALE_STRING — сравнивание значений в виде строки в текущей локалке. Вы можете обновить локалку самостоятельно, используя setlocale().
  5. SORT_NATURAL — сортирует элементы, используя «естественный порядок» и сравнивая их как строки.
  6. SORT_FLAG_CASE — этот параметр можно комбинировать с SORT_STRING или SORT_NATURAL для отключения чувствительности к регистру при сортировке строк.

Вот несколько примеров, которые помогут вам быстро понять разницу между всеми типами сортировки.

<?php

$random_data = [32508, 98134, «234984», «3249832», «38», 123, «Apple»];

sort($random_data);
echo «Regular Sorting — «;
foreach($random_data as $element) {
echo str_pad($element, 9).» «;
}
// Regular Sorting — 38 123 32508 98134 234984 3249832 Apple

sort($random_data, SORT_NUMERIC);
echo «nNumeric Sorting — «;
foreach($random_data as $element) {
echo str_pad($element, 9).» «;
}
// Numeric Sorting — Apple 38 123 32508 98134 234984 3249832

sort($random_data, SORT_STRING);
echo «nString Sorting — «;
foreach($random_data as $element) {
echo str_pad($element, 9).» «;
}
// String Sorting — 123 234984 3249832 32508 38 98134 Apple

В примере обычной сортировки числовые строки преобразуются в их числовые значения, и сортировка выполняется соответствующим образом. Строка «Apple» не является числовой, поэтому она остается нетронутой и сравнивается как строка.

Во втором примере наводится числовая сортировка, и мы хотим, чтобы данные сортировались по числовому значению, поэтому «Apple» преобразуется в числовое значение 0 и идет первым. Остальные значения отсортированы ожидаемым образом.

В третьем примере все значения обрабатываются как строки. Это означает, что вместо сравнения числового значения 123 или 3249832 с 38 они сравниваются как строки — по одному символу за раз. Поскольку «1» предшествует «3», значение 123 считается ниже 38.

Если вы хотите отсортировать значения массива от высокого к низкому вместо низкого к высокому, вы можете сделать это с помощью функции rsort().  Он принимает все те же параметры, что и sort(),  сортируя значения в обратном порядке. Он также не поддерживает ассоциации ключевых значений, поэтому это неподходящий способ для сортировки ассоциативных массивов.

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

Ассоциации ключевых значений важны, в случае если вы имеете дело с ассоциативными массивами. Рассмотрим следующий пример, где ассоциативный массив используется для хранения имен разных людей и их любимых фруктов.  Если вы хотите отсортировать список в алфавитном порядке по названию фруктов, использование функции sort() из предыдущего раздела приведет к потере ассоциативных ключей.

<?php

$fruit_preferences = [«James» => «Orange», «John» => «Banana», «Patricia» => «Apple», «Jennifer» => «Mango», «Mary» => «Grapes»];

echo «Before Sorting — n»;
foreach($fruit_preferences as $person=>$preference) {
echo $person.» likes «.$preference.»n»;
}

/*
Before Sorting —
James likes Orange
John likes Banana
Patricia likes Apple
Jennifer likes Mango
Mary likes Grapes
*/

sort($fruit_preferences);

echo «After Sorting — n»;
foreach($fruit_preferences as $person=>$preference) {
echo $person.» likes «.$preference.»n»;
}

/*
After Sorting —
0 likes Apple
1 likes Banana
2 likes Grapes
3 likes Mango
4 likes Orange
*/

?>

Как видите, мы не только потеряли взаимосвязь между людьми и их любимыми фруктами, мы также потеряли имена этих людей. Каждому отсортированному значению был присвоен новый числовой индекс, основанный на его позиции в отсортированном массиве.

Чтобы легко решить эту проблему, в PHP есть две разные функции, поддерживающие взаимосвязь между ассоциациями ключевых значений, сортируя массивы по их значениям.  Этими двумя функциями являются asort() и arsort(). Следующий фрагмент кода сортирует тот же массив $fruit_preferences, но использует функцию asort().

<?php

$fruit_preferences = [«James» => «Orange», «John» => «Banana», «Patricia» => «Apple», «Jennifer» => «Mango», «Mary» => «Grapes»];

echo «Before Sorting — n»;
foreach($fruit_preferences as $person=>$preference) {
echo $person.» likes «.$preference.»n»;
}

/*
Before Sorting —
James likes Orange
John likes Banana
Patricia likes Apple
Jennifer likes Mango
Mary likes Grapes
*/

asort($fruit_preferences);

echo «After Sorting — n»;
foreach($fruit_preferences as $person=>$preference) {
echo $person.» likes «.$preference.»n»;
}

/*
After Sorting —
Patricia likes Apple
John likes Banana
Mary likes Grapes
Jennifer likes Mango
James likes Orange
*/

?>

Как видно из приведенного выше примера, значение Apple движется к верху, сохраняя при этом свою связь с Patricia. Названия фруктов можно так же легко сортировать и в обратном порядке, используя функцию arsort().

Обе эти функции принимают те же значения сортировки, как и значения необязательного второго параметра: sort() и rsort().

Сортировка элементов массива по значению с помощью пользовательских функций

С помощью разных значений вашим потребностям могут соответствовать четыре функции сортировки.  Однако иногда ваши критерии сравнения элементов массива могут отличаться.

Допустим, у вас есть массив случайных слов, которые нужно отсортировать по алфавиту.  Но перед этим вы ещё хотите их отсортировать по длине. Например, в традиционной алфавитной сортировке zoo будет следовать за apple.  С другой стороны, если вы хотите показать сначала короткие слова, а потом длинные, то zoo появится перед apple. В том же наборе букв, ape будет перед zoo из-за алфавитного порядка.

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

Для таких случаев PHP предоставляет вам пару функций, которые можно использовать для передачи массива, подлежащий сортировке, вместе с именем вашей собственной функции сортировки.

Используйте функцию usort() для сортировки значений массива в обычных массивах. Точно так же можно использовать функцию uasort() для сортировки значений в ассоциативных массивах, сохраняя при этом ассоциаций ключевых значений.

Этот фрагмент кода показывает один из способов выполнения данной сортировки.

<?php

$random_words = [«ape», «apple», «zoo», «pie», «elephant», «banana», «picnic», «eye»];

sort($random_words);
echo «Regular Sort Function: n»;
foreach($random_words as $element) {
echo str_pad($element, 9).» «;
}

/*
Regular Sort Function:
ape apple banana elephant eye picnic pie zoo
*/

function custom_sort($word_a, $word_b) {
if (strlen($word_a) < strlen($word_b)) {
return -1;
}
if (strlen($word_a) == strlen($word_b)) {
return strcmp($word_a, $word_b);
}
if (strlen($word_a) > strlen($word_b)) {
return 1;
}
}

usort($random_words, «custom_sort»);
echo «nCustom Sort Function: n»;
foreach($random_words as $element) {
echo str_pad($element, 9).» «;
}

/*
Custom Sort Function:
ape eye pie zoo apple banana picnic elephant
*/

?>

В функциях обратного вызова, предназначенных для пользовательской сортировки, мы должны вернуть целое число меньше 0, чтобы указать, что первое значение меньше второго. Если первое значение равно второму, возвращается 0. Если первое значение больше второго, возвращается целое число больше 0.

Поскольку нашим основным критерием сортировки была длина строки, мы напрямую возвращаем -1, если первое слово короче второго.  Точно так же мы возвращаем 1, если первое слово длиннее второго. Когда два слова имеют одинаковую длину, мы сравниваем их в алфавитном порядке с помощью функции strcmp() и возвращаем их значение.

Как вы видите, в результате наша пользовательская функция сортировки переставляет слова в точности так, как мы хотели.

Сортировка массива по ключу

Сортировка массива на основе его ключей как всегда полезна, когда вы имеете дело с ассоциативными массивами. Например, у вас может быть массив с информацией общего количества аэропортов в разных странах.  Предполагая, что названия разных стран являются ключами, а количество аэропортов — значениями, вы можете отсортировать названия стран по алфавиту. Это очень легко сделать с помощью функций ksort() и krsort().  Функция ksort() сортирует ключи от низкого к высокому, а krsort() сортирует ключи от высокого к низкому. 

Вот основной пример сортировки:

<?php

$airport_count = [«United States» => 13513, «Brazil» => 4093, «Mexico» => 1714, «Canada» => 1467, «Russia» => 1218, «Argentina» => 1138, «Bolivia» => 855, «Colombia» => 836, «Paraguay» => 799, «Indonesia» => 673];

ksort($airport_count);

foreach($airport_count as $country=>$count) {
echo str_pad($country, 15).» «.$count.»n»;
}

/*
Argentina 1138
Bolivia 855
Brazil 4093
Canada 1467
Colombia 836
Indonesia 673
Mexico 1714
Paraguay 799
Russia 1218
United States 13513
*/

?>

Вместо собственной пользовательской функции для сортировки ключей массива вы можете использовать стандартную PHP функцию uksort(). На ряду usort(), функция обратного вызова в uksort() также требует возврата  целого числа меньше 0, если первый ключ считается меньше второго, и целого числа больше 0, если первый ключ больше второго.  Эта функция также поддерживает ассоциации ключевых значений для элементов массива.

<?php

$airport_count = [«United States» => 13513, «Brazil» => 4093, «Mexico» => 1714, «Canada» => 1467, «Russia» => 1218, «Argentina» => 1138, «Bolivia» => 855, «Colombia» => 836, «Paraguay» => 799, «Indonesia» => 673];

function custom_sort($word_a, $word_b) {
if (strlen($word_a) < strlen($word_b)) {
return -1;
}
if (strlen($word_a) == strlen($word_b)) {
return strcmp($word_a, $word_b);
}
if (strlen($word_a) > strlen($word_b)) {
return 1;
}
}

uksort($airport_count, «custom_sort»);

foreach($airport_count as $country=>$count) {
echo str_pad($country, 15).» «.$count.»n»;
}

/*
Brazil 4093
Canada 1467
Mexico 1714
Russia 1218
Bolivia 855
Colombia 836
Paraguay 799
Argentina 1138
Indonesia 673
United States 13513
*/

?>

В приведенном выше примере, чтобы отсортировать названия стран по длине их названия, а затем по алфавиту, мы использовали пользовательскую функцию сортировки из предыдущего раздела.

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

В реальных проектах чаще всего имеют дело с многомерной информацией. Например, учебные заведения будут хранить оценки по разным предметам всех учащихся в одной таблице вместо создания новых таблиц для каждого предмета. Если вам понадобилось бы хранить похожую информацию в PHP, вы тоже предпочли использовать данный подход,а именно  многомерный массив вместо отдельного массива для каждого предмета.

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

Если вы хотите отсортировать значения в многомерном массиве на основе определенного поля, вы можете просто использовать функцию usort(). Приведенный ниже пример поможет вам лучше понять эту технику.

<?php

$tallest_buildings = [
[«Building» => «Burj Khalifa»,»City» => «Dubai»,»Country» => «United Arab Emirates»,»Height» => 828,»Floors» => 163,»Year» => 2010],
[«Building» => «Shanghai Tower»,»City» => «Shanghai»,»Country» => «China»,»Height» => 632,»Floors» => 128,»Year» => 2015],
[«Building» => «Abraj Al-Bait Towers»,»City» => «Mecca»,»Country» => «Saudi Arabia»,»Height» => 601,»Floors» => 120,»Year» => 2012],
[«Building» => «Ping An Finance Center»,»City» => «Shenzhen»,»Country» => «China»,»Height» => 599,»Floors» => 115,»Year» => 2017],
[«Building» => «Lotte World Tower»,»City» => «Seoul»,»Country» => «South Korea» ,»Height» => 554,»Floors» => 123,»Year» => 2016]
];

function storey_sort($building_a, $building_b) {
return $building_a[«Floors»] — $building_b[«Floors»];
}

usort($tallest_buildings, «storey_sort»);

foreach($tallest_buildings as $tall_building) {
list($building, $city, $country, $height, $floors) = array_values($tall_building);
echo $building.» is in «.$city.», «.$country.». It is «.$height.» meters tall with «.$floors.» floors.n»;
}

/*
Ping An Finance Center is in Shenzhen, China. It is 599 meters tall with 115 floors.
Abraj Al-Bait Towers is in Mecca, Saudi Arabia. It is 601 meters tall with 120 floors.
Lotte World Tower is in Seoul, South Korea. It is 554 meters tall with 123 floors.
Shanghai Tower is in Shanghai, China. It is 632 meters tall with 128 floors.
Burj Khalifa is in Dubai, United Arab Emirates. It is 828 meters tall with 163 floors.
*/

?>

В приведенном выше примере информация о каждом здании хранится в своем собственном массиве внутри основного массива $tallest_buildings. Функция storey_sort() просто вычитает количество этажей во втором здании, начиная с первого, чтобы определить, какое по нашим критериям здание меньше.  Не следует беспокоиться о возврате определенного отрицательного или положительного значения, потому что все отрицательные значения означают меньшее, а все положительные значения означают большее.

В конце мы просто перебираем основной массив и выводим информацию о каждом здании.

Послесловие

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

Я надеюсь, что в этом уроке вы узнали что-то новое. Если у вас есть какие-либо вопросы или предложения, пожалуйста, сообщите в комментариях. Лучший способ научиться — это попробовать создать собственные примеры сортировки массивов на основе вышеуказанных функций.

Источник: code.tutsplus.com