Главное меню

Сортировка массивов

Часто бывает нужно выполнить сортировку однотипных данных, находящихся в массиве. Сортировка одномерного массива достаточно проста.

Использование функции sort ()

Показанный ниже код, в котором используется функция sort (), упорядочивает массив в алфавитном порядке:

$products = array ( 'Покрышки', 'Масло', 'Свечи зажигания' );

sort($products);

Теперь элементы массива будут расположены в следующем порядке: Масло, Покрышки, Свечи зажигания.

Значения можно упорядочивать также и в цифровом порядке. При наличии массива, содержащего цены на товары, поставляемые компанией “Автозапчасти от Вована”, его можно отсортировать в порядке возрастания числовых значений, например:

$prices = array (100, 10, 4) ;

sort($prices);

Теперь цены будут приведены в следующем порядке: 4, 10, 100.

Обратите внимание на то, что функция sort () чувствительна к регистру, т.е. прописные буквы предшествуют строчным. Так, “А” меньше “Z”, но “Z” меньше “а”.

Кроме того, функция sort () может принимать необязательный второй параметр, который может быть равен одной из следующих констант: SORT_REGULAR (по умолчанию), SORT_NUMERIC или SORT_STRING. Возможность указания типа сортировки полезна, когда выполняется сравнение строк, содержащих числа, скажем, 2 и 12. С точки зрения чисел 2 меньше 12, однако, строка ' 12 ' будет меньше строки ' 2 '.

Использование функций asort () и ksort () для сортировки массивов

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

Следующий код создает массив с описательными индексами, содержащий три товара и связанные с ними цены, а затем сортирует массив в порядке возрастания цен:

$prices = array( 'Покрышки'=>100, 'Масло'=>10, 'Свечи зажигания'=>4 );

asort($prices);

Функция asort () (“array sort” – “сортировка массива”) упорядочивает массив в соответствии со значениями элементов. В данном массиве значениями являются цены, а в качестве ключей выбраны текстовые описания товаров. Если сортировку требуется выполнить не по ценам, а по описаниям, следует воспользоваться функцией ksort () (“key sort” – “ключевая сортировка”), которая, как должно быть понятно, выполняет сортировку не по значениям, а по ключам. Показанный далее код приведет к упорядочению ключей массива в алфавитном порядке: Масло, Покрышки, Свечи зажигания.

$prices = array( 'Покрышки'=>100, 'Масло'=>10, 'Свечи зажигания'=>4 );

ksort($prices);

Сортировка в обратном порядке

Мы рассмотрели функции sort (), asort () и ksort (). Все эти функции выполняют сортировку массива в порядке возрастания. Каждая из них имеет соответствующую ей функцию, которая выполняет сортировку массива в порядке убывания. Обратными функциями являются, соответственно, rsort (), arsort () и krsort ().

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

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

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

Определяемые пользователем функции сортировки

Ниже приводится определение ранее использованного двумерного массива. В этом массиве хранятся коды товаров трех видов, поставляемых компанией "Автозапчасти от Вована", их названия и цены.

$products = array( array( 'TIR', 'Покрышки', 100 ),

array( 'OIL', 'Масло', 10 ) ,

array( 'SPK', 'Свечи зажигания', 4 ) );

В каком порядке расположатся значения, если выполнить сортировку этого массива? Поскольку известно, что представляет данный массив, существует, по меньшей мере, два полезных порядка сортировки. Товары можно упорядочить в алфавитном порядке по описаниям или в цифровом порядке по ценам. И то, и другое одинаково возможно, но в данном случае мы хотим воспользоваться функцией usort () (“user sort” – “пользовательская сортировка”) и указать РНР, как следует сравнивать элементы.

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

function compare($х, $у) {

if ($х[1] == $у[1]) {

return 0;

} else if ($х[1] < $у[1]) {

return -1;

}else {

return 1;

}

}

usort($products, 'compare');

До сих пор мы использовали встроенные РНР-функции. Для сортировки этого массива должна быть определена своя собственная, т.е. “пользовательская”, функция. Вопросы создания функций будут подробно рассматриваться далее, а пока мы приводим только краткое описание этого процесса.

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

Применительно к рассматриваемому примеру, параметрами х и у будут два массива внутри основного массива, каждый из которых представляет один вид товара. Чтобы обратиться к элементу Description массива х, необходимо ввести $х[1], поскольку Description есть второй элемент в этом массиве, а нумерация начинается с нуля. Для сравнения элементов Description из массивов, переданных в функцию, используются переменные $х[1] и $у[ 1 ].

Когда функция завершает свою работу, она может вернуть ответ в вызвавший ее код. Эта операция называется возвратом значения. Для возврата значения из функции служит ключевое слово return. Например, строка return 1; возвращает значение 1 коду, вызвавшему эту функцию.

Чтобы функция compare () могла быть использована в usort (), она должна сравнивать х и у. Функция compare () должна возвращать 0, если значение х равно значению у, отрицательное число, если значение х меньше у, и положительное – если значение х больше у. Наша функция будет возвращать значения 0, 1 или -1 в зависимости от значений х и у. Заключительная строка кода вызывает встроенную функцию usort () с массивом, в котором нужно выполнить сортировку ($products) и именем нашей функции сравнения (compare ()).

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

function compare($х, $у) {

if ($х[2] == $у[2]) {

return 0;

}else if ($х[2] < $у[2]) {

return -1;

}else {

return 1;

}

}

При вызове функции usort ($products, compare) массив будет упорядочен в порядке возрастания цен.

<<Возможно, вы захотите проверить эти кодовые фрагменты, но они ничего не выводят на экран. Они предназначены для вставки в большие программы, которые вам может понадобиться написать.>>

Символ “u” в имени usort () означает “user” (“пользовательская”), поскольку этой функции требуется функция сравнения, определяемая пользователем. Версии uasort () и uksort () функций asort () и ksort () также требуют применения определяемых пользователем функций сравнения.

Подобно asort (), функция uasort () используется при сортировке массива с описательными индексами по значениям. Функцию asort следует применять, если значения являются простыми числами или текстом. Если же значения представлены более сложными объектами, такими как массивы, следует определить функцию сравнения и использовать функцию uasort ().

Так же, как и ksort (), функция uksort () должна использоваться при сортировке массива с описательными индексами по значениям. Функцию ksort () следует применять, когда значения являются простыми числами или текстом. Если же значения являются более сложными объектами наподобие массивов, следует определить функцию сравнения и воспользоваться функцией uksort ().

Определяемая пользователем сортировка в обратном порядке

Функции sort (), asort () и ksort () имеют соответствующие функции сортировки в обратном порядке; их имена содержат символ “r”. Определяемые пользователем функции сортировки не имеют обратных версий, тем не менее, можно выполнять и обратную сортировку многомерных массивов. Поскольку выбор функции сравнения остается за вами, напишите функцию сравнения, возвращающую противоположные значения. Чтобы можно было выполнить обратную сортировку, эта функция должна возвращать значение 1, если х меньше у, и -1, если х больше у.

Например:

function reverse_compare($х, $у) {

if ($х[2] == $у[2]) {

return 0;

}else if ($х [2] < $у[2]) {

return 1;

}else {

return -1;

}

}

Теперь вызов функции usort ($products, reverseCompare) приведет к тому, что элементы массива будут следовать в порядке убывания цен.

Изменение порядка следования элементов в массивах

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

Использование функции shuffle ()

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

Сортировка массивов

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

Сортировка массивов

Использование функции array_reverse ()

Функция array_reverse () принимает массив и создает новый массив, элементы которого расположены в обратном порядке. Например, существует множество способов создания массива, содержащего убывающую последовательность чисел от 10 до 1.

Использование функции range () обычно приводит к созданию возрастающей последовательности; ее можно изменить на убывающую с помощью функций array_reverse () или rsort (). Либо можно создать такой массив, занося в него по одному элементу в цикле for:

$numbers = array();

for ($i = 10; $i > 0; $i --) {

array_push($numbers, $i) ;

}

Цикл for может выполняться и в порядке убывания, как показано в этом примере. Начальное значение устанавливается большим, в конце каждого цикла операция декремента -- уменьшает значение счетчика на единицу.

В данном примере создается пустой массив, а затем применяется функция аггау_ push () для добавления каждого нового элемента в конец массива. Попутно следует отметить, что обратной функцией для array_push () является функция аггау_рор (). Эта функция удаляет и возвращает один элемент из конца массива.

Можно также воспользоваться функцией array_reverse () для изменения порядка следования элементов массива, созданного функцией range ().

$numbers = range(1,10);

$numbers = array_reverse($numbers);

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

Если данные должны быть диапазоном целых чисел, обратного порядка можно добиться, вызвав range () и передав -1 в необязательном третьем параметре:

$numbers = range (10, 1, -1);