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

Introduction

Sorting functions in PHP are currently unstable, which means that the order of “equal” elements is not guaranteed. This RFC proposes to make all sorts in PHP stable.

If multiple elements in the input array compare equal, they will always be sorted adjacently. However, if the sort is unstable, their relative order is not guaranteed, and will appear to be random. A stable sort guarantees that equal elements will retain the order they had in the original array.

Stable sorts are useful primarily when sorting complex data only by some part of that data. Consider this example:

usort($users, function($user1, $user2) {
    return $user1->age <=> $user2->age;
});

This code sorts users by age. Currently, the order of users in one age bracket will be arbitrary. With a stable sort, the original order of the objects will be retained. For example, if was already sorted by name, then will now be sorted by age first and name second. Of course, in this case it would be possible to explicitly sort by two criteria:

usort($users, function($user1, $user2) {
    return $user1->age <=> $user2->age
        ? $user1->name <=> $user2->name;
});

However, this is not always possible, because the criterion by which the data was originally sorted is not explicitly stored. A recent case I ran into was a list of git commits with metadata, which were stored in push order (but the push order was not explicitly stored on each commit).

Apart from user-supplied comparison functions, another case where stable sorting is often desirable is the function, which sorts by value, but preserves keys.

$array = 
    'c' => 1,
    'd' => 1,
    'a' => ,
    'b' => ,
;
asort($array);
 
// With stable sorting, the result is always:
'a' => , 'b' => , 'c' => 1, 'd' => 1
 
// With unstable sorting, the following results are also possible:
'b' => , 'a' => , 'c' => 1, 'd' => 1
'a' => , 'b' => , 'd' => 1, 'c' => 1
'b' => , 'a' => , 'd' => 1, 'c' => 1

It is possible to emulate a stable sort on top of an unstable one by explicitly storing the original order of the elements and using it as a fallback comparison criterion. For example, a stable sort implementation could look like this:

function stable_usort(array &$array, callable $compare) {
    $arrayAndPos = ;
    $pos = ;
    foreach ($array as $value) {
        $arrayAndPos = $value, $pos++;
    }
    usort($arrayAndPos, function($a, $b) use($compare) {
        return $compare($a, $b) ? $a1 <=> $b1;
    });
    $array = ;
    foreach ($arrayAndPos as $elem) {
        $array = $elem;
    }
}

While this approach works, it is also highly inefficient. The additional indirection makes sorting much slower, and will also skyrocket memory usage during sorting.

Операции с массивами

Последнее обновление: 1.11.2015

Функция is_array

Функция проверяет, является ли переменная массивом, и если является, то возвращает , иначе возвращает
. Например:

$isar = is_array($technics);
echo ($isar==true)?"это массив":"это не массив";

Функции count/sizeof

Функция и получают количество элементов массива:

$number = count($technics);
// то же самое, что
// $number = sizeof($technics);
echo "В массиве technics $number элементов";

Функции 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

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

<?php

$model = "Apple II";
$producer = "Apple";
$year = 1978;

$data = compact('model', 'producer', 'year');
print_r($data);
// получится следующий вывод
// Array (  => Apple II  => Apple  => 1978 ) 
?>

Функция compact получает в скобках набор переменных. Каждая переменная указывается в кавычка без знака $. Результатом функции является новый массив.

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

В PHP имеются два типа сортировки: сортировка строк по алфавиту и сортировка чисел по возрастанию/убыванию. Если сортируемые значения представляют строки,
то они сортируются по алфавиту, если числа — то они сортируются в порядке возрастания чисел. PHP по умолчанию самостоятельно выбирает тип сортировки.

Для сортировки по возрастанию используется функция asort:

<?php
$tablets = array("lenovo" => "Lenovo IdeaTab A3500", 
						"samsung" => "Samsung Galaxy Tab 4",
						"apple" => "Apple iPad Air");
asort($tablets);

echo "<ul>";
foreach ($tablets as $key => $value)
{
	echo "<li>$key : $value</li>";
}
echo "</ul>";
?>

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

  • : автоматический выбор сортировки

  • : числовая сортировка

  • : сортировка по алфавиту

Укажем явно тип сортировки:

asort($tablets, SORT_STRING);

Чтобы отсортировать массив в обратном порядке, применяется функция arsort:

arsort($tablets);

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

Функция производит сортировку по значениям элементов, но также существует и еще и сортировка по ключам. Она представлена функцией
ksort:

ksort($tablets, SORT_STRING);

Сортировка по ключам в обратном порядке выполняется функцией krsort():

krsort($tablets);

Естественная сортировка

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

<?php
$os = array("Windows 7", "Windows 8", "Windows 10");
asort($os);
print_r($os);
// результат
// Array (  => Windows 10  => Windows 7  => Windows 8 ) 
?>

Так как значения представляют строки, то PHP сортирует по алфавиту. Однако подобная сортировка не учитывает числа и регистр. Поэтому значение
«Windows 10» будет идти в самом начале, а не в конце, как должно было быть. И для решения этой проблемы в PHP есть функция natsort(),
которая выполняет естественную сортировку:

<?php
$os = array("Windows 7", "Windows 8", "Windows 10");
natsort($os);
print_r($os);
// результат
// Array (  => Windows 7  => Windows 8  => Windows 10) 
?>

Если нам надо еще при этом, чтобы сортировка не учитывала регистр, то мы можем применить функцию natcasesort():

natcasesort($os);

НазадВперед

Proposal

This RFC proposes to make all PHP sorting functions stable. This includes sort, rsort, usort, asort, arsort, uasort, ksort, krsort, uksort, array_multisort, as well as corresponding methods on ArrayObject.

Implementation

The underlying sort implementation remains an unstable hybrid quick sort. Stability is achieved by storing the original order of the array elements and using that order as a fallback sorting criterion.

This matches what is implemented in the PHP code above, with the difference that certain internal implementation details allow us to do this highly efficiently, without increasing memory usage.

An alternative would be to change the underlying sorting algorithm to Timsort, which is inherently stable.

Illegal comparison functions

PHP documents that comparison functions must return an integer smaller than, equal to, or greater than zero. However, due to the specific implementation of sorting in PHP, it is currently also possible to return a boolean that indicates whether the value is greater:

usort($values, function($a, $b) {
    // Should be $a <=> $b !
    return $a > $b;
});

This works, because PHP currently only checks whether the comparison result is “greater than” or not, and never explicitly distinguishes the “equal” and “smaller than” cases. This breaks down with the approach proposed here, because we now do need to know whether values are equal or not, in order to use the fallback sorting criterion.

This RFC takes two steps to address this. First, a deprecation warning will be emitted if a boolean is returned from a custom comparison function. The deprecation warning is thrown only once per sort:

Second, if boolean false is returned, PHP will automatically call the comparison function again with arguments swapped. This allows us to distinguish whether the “false” stood for “equal” or “smaller than”. This fallback behavior should be removed in a future version of PHP.

Пользовательская сортировка

Также мы можем задать и свои порядок сортировки, то есть создать пользовательскую сортировку.

Для этого также в php предусмотрены специальные функции.

Для пользовательской сортировки списков предусмотрена функция usort().

Она будет принимать два аргумента. Первый аргумент – это наш массив; второй аргумент – будет содержать имя функции, сравнивающей два элемента.

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

1 – если первый элемент сравнения больше второго;

-1 – если второй больше первого;

0 – если элементы равны.

Таким образом мы, например, можем отсортировать элементы массива по возрастанию их длины.

Для этого сначала объявим сам массив, который будет содержать строковые элементы различной длины.

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

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

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

<?
$Mass = array('Андрей', 'Яна', 'Катя');
function check_length($str1,$str2){
$length1 = strlen($str1);
$length2 = strlen($str2);
if($length1 == $length2):
return 0;
elseif($length1 < $length2):
return -1;
else:
return 1;
endif;	
}
usort($Mass,"check_length");
print_r($Mass);
?>

Получим мы следующий результат. Элементы нашего массива отсортированы в порядке увеличения их длины.

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

Давайте оставим пользовательскую функцию той же, то есть сравниваем длину ключей.

<?
$Mass='яна';
$Mass='андрей';
$Mass='катя';
function check_length($str1,$str2){
$length1 = strlen($str1);
$length2 = strlen($str2);
if($length1 == $length2):
return 0;
elseif($length1 < $length2):
return -1;
else:
return 1;
endif;	
}
uksort($Mass,"check_length");
print_r($Mass);
?>

Ключи элементов массива отсортированы по возрастанию их длины.

И также мы можем создать пользовательскую сортировку ассоциативного массива по значениям его элементов. В этом нам поможет функция uasort().

Принцип все тот же.

<?
$Mass='яна';
$Mass='андрей';
$Mass='катя';
function check_length($str1,$str2){
$length1 = strlen($str1);
$length2 = strlen($str2);
if($length1 == $length2):
return 0;
elseif($length1 < $length2):
return -1;
else:
return 1;
endif;	
}
uasort($Mass,"check_length");
print_r($Mass);
?>

Теперь массив отсортирован по увеличению длин его значений.

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

Чтобы хорошенько понять, как работает пользовательская сортировка, нужно попрактиковаться и попробовать написать какую-то свою функцию сравнения.

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

Практикуйтесь, пишите Ваши комментарии и делитесь статьей с друзьями при помощи кнопок социальных сетей.

Если Вы еще не подписаны на обновления блога, то подписывайтесь. Форма подписки находится ниже.

С Вами была Анна Котельникова. До встречи в следующих статьях.

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

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

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

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

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

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

Сортировка сложных и многомерных массивов с array_multisort()

Очень мощная функция array_multisort() может сортировать многомерный массив, сохраняя связь между массивами. Вобщем, сейчас всё увидим:

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

Сортируем, используя array_multisort(), просто указываем те массивы, которые нужно обратотать:

 $directors = array( "Stanley Kubrick", "Alfred Hitchcock", "Martin Scorsese" ); $titles = array( "Full Metal Jacket", "Rear Window", "Mean Streets" ); $years = array( 1987, 1954, 1973 ); array_multisort( $directors, $titles, $years ); print_r( $directors ); echo "<br />"; print_r( $titles ); echo "<br />"; print_r( $years ); echo "<br />"; 

Этот код отобразит: Array ( => Alfred Hitchcock => Martin Scorsese => Stanley Kubrick ) Array ( => Rear Window => Mean Streets => Full Metal Jacket ) Array ( => 1954 => 1973 => 1987 ) Сначала array_multisort() сортирует значения в $directors в возрастающем порядке, затем 2 остальных так же.

А что если мы хотим сортировать, например, чтобы вначале «title»? Просто положите $titles вперёд списка:

 array_multisort( $titles, $directors, $years ); 

Сортировка по… далее…

Если первый массив содержит какое-то количество id-номеров, тогда array_multisort() сортирует по этим значениям первый массив, затем — второй, и тд. Пример:

 $directors = array( "Stanley Kubrick", "Alfred Hitchcock", "Martin Scorsese", "Stanley Kubrick" ); $titles = array( "Full Metal Jacket", "Rear Window", "Mean Streets", "A Clockwork Orange" ); $years = array( 1987, 1954, 1973, 1971 ); array_multisort( $directors, $titles, $years ); print_r( $directors ); echo "<br />"; print_r( $titles ); echo "<br />"; print_r( $years ); echo "<br />"; 

Этот код выдаёт следующее — заметьте, что «A Clockwork Orange» перед «Full Metal Jacket»: Array ( => Alfred Hitchcock => Martin Scorsese => Stanley Kubrick => Stanley Kubrick ) Array ( => Rear Window => Mean Streets => A Clockwork Orange => Full Metal Jacket ) Array ( => 1954 => 1973 => 1971 => 1987 )

Меняем порядок сортировки

Вы можете пропустить (опционально) flag-аргумент после аргумента массива чтобы менять порядок сортировки:

SORT_ASC сортировка по возрастаниюSORT_DESC сортировка по убыванию

Тут сортируем $directors по возрастанию, затем $titles по убыванию:

 $directors = array( "Stanley Kubrick", "Alfred Hitchcock", "Martin Scorsese", "Stanley Kubrick" ); $titles = array( "Full Metal Jacket", "Rear Window", "Mean Streets", "A Clockwork Orange" ); $years = array( 1987, 1954, 1973, 1971 ); array_multisort( $directors, SORT_ASC, $titles, SORT_DESC, $years ); print_r( $directors ); echo "<br />"; print_r( $titles ); echo "<br />"; print_r( $years ); echo "<br />"; 

Вот что вышло: заметьте, что «Full Metal Jacket» теперь перед «A Clockwork Orange»:

Array ( => Alfred Hitchcock => Martin Scorsese => Stanley Kubrick => Stanley Kubrick ) Array ( => Rear Window => Mean Streets => Full Metal Jacket => A Clockwork Orange ) Array ( => 1954 => 1973 => 1987 => 1971 )

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

Сортировка через array_multisort() проходит по первому элементу каждого массива. Если 2 значения одинаковы, сортирвка идёт по 2у элементу и тп.

Это пример, который показывает, как это работает Сортировка идет по director, потом по title, потом по year:

 $movies = array( array( "director" => "Alfred Hitchcock", "title" => "Rear Window", "year" => 1954 ), array( "director" => "Stanley Kubrick", "title" => "Full Metal Jacket", "year" => 1987 ), array( "director" => "Martin Scorsese", "title" => "Mean Streets", "year" => 1973 ), array( "director" => "Stanley Kubrick", "title" => "A Clockwork Orange", "year" => 1971 ) ); array_multisort( $movies ); echo "<pre>"; print_r( $movies ); echo "</pre>"; 

Результат:

Array ( => Array ( => Alfred Hitchcock => Rear Window => 1954 )

=> Array ( => Martin Scorsese => Mean Streets => 1973 )

=> Array ( => Stanley Kubrick => A Clockwork Orange => 1971 )

=> Array ( => Stanley Kubrick => Full Metal Jacket => 1987 )

Как видите, array_multisort() отсортирвал массив по director. Когда имя режиссёра повторилось, («Stanley Kubrick»), сортировка пошла по title.

Чтобы отсортровать в обратном порядке, укажите SORT_DESC-флаг как второй аргумент array_multisort(). Просто!

Итог

В этом уроке мы посмотрели на простые PHP-функции для сортровки массива:

* sort() и rsort() для сортровки индексируемых массивов * asort() и arsort() для сортровки асоциативных массивов * ksort() и krsort() для сортровки ассоциативнх массивов по ключу * array_multisort() для сортировки для сортировки сложных и многомерных массивов

______________

Наткнулся тут на интересный блог – блог про блоги так сказать) Автор обзоры делает)

Naikom » Кодинг » PHP

Немного теории о массивах php

PHP – это серверный язык программирования. Серверный, потому что скрипты, которые запускаются пользователями через веб-интерфейс (Интернет-браузер), хранятся и выполняются на сервере.

PHP-скрипты скрыты от взора обычного пользователя. В окне ваших браузеров вы видите только результаты их выполнения.

Массив в программировании – это совокупность каких-то данных. Состоят они из элементов массива, которые представляют собой пары => .

Массивы бывают статические, динамические, гетерогенные и т.д. (целая наука) Нам же для работы с ними вполне хватит классификации на одномерные и многомерные.

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

Одномерый массив php:

Array (
    => 1

    => 2

    => 3
)

Многомерный массив php:


Array
(
    => Array (
        => 1
   )

    => Array (
        => 2
   )

    => Array (
        => 3
   )
)

Заметили? Если нет – обратите внимание на элементы многомерного массива php. Они сами являются массивами

Т.е. многомерный массив – это совокупность массивов. Уровень их вложенности может быть сколько угодно большим.

Теперь, думаю, точно понятно

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

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

Примером ассоциативного массива может служить следующая конструкция:


Array (
    => 12

    => Иванов Иван Иванович

    => 3
)

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

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

В самом php массивы создаются двумя способами:

  1. $books = array(‘Азбука’, ‘Букварь’, ‘Словарь); или $books = array(‘azb’ => ‘Азбука’, ‘buk’ => ‘Букварь’, ‘slov’ => ‘Словарь’); Второй вариант используется, когда элементу нужно явно указать ключевое поле (актуально для ассоциативных массивов). Если его не указать, по умолчанию ключи элементов массива будут числами. Начиная с 0 (нуля).
  2. $books = ‘Азбука’; $books = ‘Букварь’; $books = ‘Букварь’;

В обоих случаях $books будет являться массивом. Так что, если вы встретите в коде своего сайта такие конструкции, это уже не будет для вас чем-то непонятным

Если вы хотите узнать о массивах php более подробно, то рекомендую вашему вниманию следующее видео:

PHP урок 10 МассивыPHP урок 10 Массивы

Напомню, что для того, чтобы увидеть структуру массива у себя на экране, после объявления массива в коде сайта необходимо прописать следующую конструкцию:


echo '<pre>'; print_r(переменная_массива); die();

Если распечатываемая вами переменная будет являться массивом, то текст будет начинаться со следующей строки:


Array (
…

И ещё несколько слов о теме нашей статьи – сортировке массивов php.

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

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

Переходим к обзору самих функций.

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

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

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

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

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

Оцените статью
Рейтинг автора
5
Материал подготовил
Илья Коршунов
Наш эксперт
Написано статей
134
Добавить комментарий