uasort
Сортирует array таким образом, чтобы его ключи сохраняли свою корреляцию со значениями, с которыми они связаны, с использованием определяемой пользователем функции сравнения.
Это обычно используется при сортировке ассоциативных массивов, в которых важен актуальный порядок элементов.
Замечание:
Если оба сравниваемых значения эквивалентны, они сохраняют свой первоначальный порядок. До PHP 8.0.0 их относительный порядок в отсортированном массиве не был определён.
Замечание:
Сбрасывает внутренний указатель массива на первый элемент.
Список параметров
Функция сравнения должна возвращать целое, которое меньше, равно или больше нуля, если первый аргумент является соответственно меньшим, равным или большим, чем второй.
Возвращение нецелых значений из функции сравнения, таких как число с плавающей точкой ( float ), приведёт к внутреннему приведению возвращаемого значения callback-функции к целому числу ( int ). Таким образом, значения 0.99 и 0.1 будут приведены к целочисленному значению 0 , что позволит сравнить эти значения как равные.
Возвращаемые значения
Функция всегда возвращает true .
Список изменений
Версия | Описание |
---|---|
8.2.0 | Тип возвращаемого значения теперь true ; ранее было bool . |
8.0.0 | Если параметр callback ожидает, что будет передано значение по ссылке, функция теперь выдаст ошибку уровня E_WARNING . |
Примеры
Пример #1 Простой пример использования uasort()
// Функция сравнения
function cmp ( $a , $b ) if ( $a == $b ) return 0 ;
>
return ( $a < $b ) ? - 1 : 1 ;
>
?php
// Сортируемый массив
$array = array( ‘a’ => 4 , ‘b’ => 8 , ‘c’ => — 1 , ‘d’ => — 9 , ‘e’ => 2 , ‘f’ => 5 , ‘g’ => 3 , ‘h’ => — 4 );
print_r ( $array );
// Сортируем и выводим получившийся массив
uasort ( $array , ‘cmp’ );
print_r ( $array );
?>
Результат выполнения данного примера:
Array ( [a] => 4 [b] => 8 [c] => -1 [d] => -9 [e] => 2 [f] => 5 [g] => 3 [h] => -4 ) Array ( [d] => -9 [h] => -4 [c] => -1 [e] => 2 [g] => 3 [a] => 4 [f] => 5 [b] => 8 )
Смотрите также
- usort() — Сортирует массив по значениям используя пользовательскую функцию для сравнения элементов
- uksort() — Сортирует массив по ключам, используя пользовательскую функцию для сравнения ключей
- Сравнение функций сортировки массивов
User Contributed Notes 20 notes
a quick reminder on the syntax if you want to use uasort in a Class or Object:
// procedural:
uasort ( $collection , ‘my_sort_function’ );
// Object Oriented
uasort ( $collection , array( $this , ‘mySortMethod’ ));
// Objet Oriented with static method
uasort ( $collection , array( ‘self’ , ‘myStaticSortMethod’ ));
An Example using anonymous function.
Anonymous functions make some time the code easier to understand.
$fruits = array( ‘Orange9’ , ‘Orange11’ , ‘Orange10’ , ‘Orange6’ , ‘Orange15’ );
uasort ( $fruits , function ( $a , $b ) return strnatcmp ( $a , $b ); // or other function/code
>
);
print_r ( $fruits );
?>
returns
Array
(
[3] => Orange6
[0] => Orange9
[2] => Orange10
[1] => Orange11
[4] => Orange15
)
If you want to keep the order when two members compare as equal, use this.
function stable_uasort (& $array , $cmp_function ) if( count ( $array ) < 2 ) return;
>
$halfway = count ( $array ) / 2 ;
$array1 = array_slice ( $array , 0 , $halfway , TRUE );
$array2 = array_slice ( $array , $halfway , NULL , TRUE );
stable_uasort ( $array1 , $cmp_function );
stable_uasort ( $array2 , $cmp_function );
if( call_user_func ( $cmp_function , end ( $array1 ), reset ( $array2 )) < 1 ) $array = $array1 + $array2 ;
return;
>
$array = array();
reset ( $array1 );
reset ( $array2 );
while( current ( $array1 ) && current ( $array2 )) if( call_user_func ( $cmp_function , current ( $array1 ), current ( $array2 )) < 1 ) $array [ key ( $array1 )] = current ( $array1 );
next ( $array1 );
> else $array [ key ( $array2 )] = current ( $array2 );
next ( $array2 );
>
>
while( current ( $array1 )) $array [ key ( $array1 )] = current ( $array1 );
next ( $array1 );
>
while( current ( $array2 )) $array [ key ( $array2 )] = current ( $array2 );
next ( $array2 );
>
return;
>
function cmp ( $a , $b ) if( $a [ ‘n’ ] == $b [ ‘n’ ]) return 0 ;
>
return ( $a [ ‘n’ ] > $b [ ‘n’ ]) ? — 1 : 1 ;
>
$a = $b = array(
‘a’ => array( «l» => «A» , «n» => 1 ),
‘b’ => array( «l» => «B» , «n» => 2 ),
‘c’ => array( «l» => «C» , «n» => 1 ),
‘d’ => array( «l» => «D» , «n» => 2 ),
‘e’ => array( «l» => «E» , «n» => 2 ),
);
uasort ( $a , ‘cmp’ );
print_r ( $a );
stable_uasort ( $b , ‘cmp’ );
print_r ( $b );
?>
returns
User «php at clement dot hk» already provided a stable uasort function, but I find this wrapper much shorter and easier to understand:
function stable_uasort(array &$array, $value_compare_func) $index = 0;
foreach ($array as &$item) $item = array($index++, $item);
>
$result = uasort($array, function($a, $b) use($value_compare_func) $result = call_user_func($value_compare_func, $a[1], $b[1]);
return $result == 0 ? $a[0] — $b[0] : $result;
>);
foreach ($array as &$item) $item = $item[1];
>
return $result;
>
Difference between uasort() and usort(), the missing example .
$arr = array ( 10 => array( ‘id’ => ‘dix’ , ‘aa’ => ‘1010’ ),
100 => array( ‘id’ => ‘cent’ , ‘aa’ => ‘100100’ ),
2 => array( ‘id’ => ‘deux’ , ‘aa’ => ’22’ ),
7 => array( ‘id’ => ‘sept’ , ‘aa’ => ’77’ ));
(
[ id ] => deux
[ aa ] => 22
) [ 10 ] => Array
(
[ id ] => dix
[ aa ] => 1010
) [ 7 ] => Array
(
[ id ] => sept
[ aa ] => 77
)) ?>
*** usort($arr, ‘so’) output:
[ 1 ] => Array(
[ id ] => deux
[ aa ] => 22
) [ 2 ] => Array
(
[ id ] => dix
[ aa ] => 1010
) [ 3 ] => Array
(
[ id ] => sept
[ aa ] => 77
)) ?>
//this fix the problem of if any of these sort functions evaluates two members as equal then the order is undefined (the sorting is not stable).
$pos=0;
foreach($values as $k => $v)
$tosort[$k]=array($v,$pos++);
uasort($tosort,function($a, $b) if($a[0] != $b[0])return ($a[0] < $b[0]) ? -1 : 1;
return ($a[1] < $b[1]) ? -1 : 1;>
);
foreach($tosort as $k => $v)
$values[$k]=$v[0];
I tried using some of the previous built multisorts, but they weren’t working as expected.
So, I made my own Class, and it seems to work wonderfully.
/************************************
* Allows sorting multi-dimensional
* arrays by a specific key and in
* asc or desc order
**/
class multiSort
<
var $key ; //key in your array
//runs the sort, and returns sorted array
function run ( $myarray , $key_to_sort , $type_of_sort = » )
<
$this -> key = $key_to_sort ;
if ( $type_of_sort == ‘desc’ )
uasort ( $myarray , array( $this , ‘myreverse_compare’ ));
else
uasort ( $myarray , array( $this , ‘mycompare’ ));
//for ascending order
function mycompare ( $x , $y )
<
if ( $x [ $this -> key ] == $y [ $this -> key ] )
return 0 ;
else if ( $x [ $this -> key ] < $y [ $this ->key ] )
return — 1 ;
else
return 1 ;
>
//for descending order
function myreverse_compare ( $x , $y )
<
if ( $x [ $this -> key ] == $y [ $this -> key ] )
return 0 ;
else if ( $x [ $this -> key ] > $y [ $this -> key ] )
return — 1 ;
else
return 1 ;
>
>
?>
Is it just me, or are the examples below misleading, and actually demonstrating situations that would be more appropriate for usort()?
After trying to make sense of the uasort() description, it sounds like it’s more for sorting a 1D array like this:
(assuming, of course, that your sort function is lopping off the $ and evaluating as a number — which would complicate the use of asort() 😉
$array[0][‘Fator1’]=7;
$array[0][‘Fator2’]=»Name»;
$array[1][‘Fator1’]=5;
$array[1][‘Fator2’]=»Name»;
$array[2][‘Fator1’]=7;
$array[2][‘Fator2’]=»NameDiferente»;
.
We want to order by Fator1, then Fator2, then:
function Compare($ar1, $ar2)
<
if ($ar1[‘Fator1’] <$ar2['Fator1'])
return -1;
else if ($ar1[‘Fator1’]>$ar2[‘Fator1’])
return 1;
if ($ar1[‘Fator2’] <$ar2['Fator2'])
return -1;
else if ($ar1[‘Fator2’]>$ar2[‘Fator2’])
return 1;
return 0;
>
To shuffle assoc array preserving keys just do this:
$array ,
function ( $a , $b ) <
return mt_rand ( 0 , 1 ) > 0 ? 1 : — 1 ;
>
); ?>
Сортировка массивов
В PHP есть несколько функций для сортировки массивов, на этой странице даётся их общее описание.
Основные различия между функциями:
- В одних функциях массивы ( array ) сортируются по ключам элементов, в других по значениям: $array[‘ключ’] = ‘значение’;
- В каких-то функциях связь между ключами и значениями после сортировки сохраняется, в каких-то нет. Это может приводить к тому, что ключи будут сбрасываться в числовые значения (0, 1, 2, . ).
- Различия в порядке сортировки: алфавитный, возрастающий, убывающий, числовой, естественный, случайный или определённый пользователем
- Примечание: Все функции сортировки модифицируют переданный массив, а не возвращают отсортированную копию
- Если какая-либо из этих функций сортировки оценивает два элемента как равные, они сохраняют свой исходный порядок. До PHP 8.0.0 их порядок не был определён (сортировка была нестабильной).
Имя функции | Сортирует по | Сохраняет связь ключ — значение | Порядок сортировки | Похожие функции |
---|---|---|---|---|
array_multisort() | значению | строковые ( string ) ключи да, числовые ( int ) — нет | первый массив или настройки сортировки | array_walk() |
asort() | значению | да | по возрастанию | arsort() |
arsort() | значению | да | по убыванию | asort() |
krsort() | ключу | да | по убыванию | ksort() |
ksort() | ключу | да | по возрастанию | krsort() |
natcasesort() | значению | да | естественный, нечувствительный к регистру | natsort() |
natsort() | значению | да | естественный | natcasesort() |
rsort() | значению | нет | по убыванию | sort() |
shuffle() | значению | нет | случайный | array_rand() |
sort() | значению | нет | по возрастанию | rsort() |
uasort() | значению | да | определяется пользователем | uksort() |
uksort() | ключу | да | определяется пользователем | uasort() |
usort() | значению | нет | определяется пользователем | uasort() |
User Contributed Notes 2 notes
While this may seem obvious, user-defined array sorting functions ( uksort(), uasort(), usort() ) will *not* be called if the array does not have *at least two values in it*.
function usortTest ( $a , $b ) var_dump ( $a );
var_dump ( $b );
return — 1 ;
>
$test = array( ‘val1’ );
usort ( $test , «usortTest» );
$test2 = array( ‘val2’ , ‘val3’ );
usort ( $test2 , «usortTest» );
The first array doesn’t get sent to the function.
Please, under no circumstance, place any logic that modifies values, or applies non-sorting business logic in these functions as they will not always be executed.
Another way to do a case case-insensitive sort by key would simply be:
uksort ( $array , ‘strcasecmp’ );
?>
Since strcasecmp is already predefined in php it saves you the trouble to actually write the comparison function yourself.
PHP — написание простого quicksort
Не так давно мне пришлось искать новую работу в сфере веб разработки (PHP разработчик).
На одном из собеседований в достаточно крупную фирму, было некое подобие коллективного собеседования. Всех пригласили в одну аудиторию, раздали тесты и там же говорили с каждым кандидатом. Одним из вопросов, на котором «пролетели» большинство участников собеседования — алгоритм и реализация быстрой сортировки по массиву (quicksort). Некоторые не смогли реализовать, а некоторые даже написать его. В связи с этим, хочу помочь в понимании и написании и реализации этого алгоритма.
Итак, описание алгоритма:
- Необходимо выбрать элемент, на который будет опираться сортировка.
Идеальный вариант — среднее число в массиве, тогда будет выполнена наименее емкая и наиболее быстрая сортировка, за меньшее количество проходов. - Далее, опираясь на выбранный ранее центральный элемент, разделяем массив на часть которая больше этого элемента, и часть, которая меньше его.
Делается это путем обмена элементов относительно выбранного центра. - После прохода по массиву, рекурсивно вызываем функцию еще раз, для левой и правой части
Далее приведу свой код, с комментариями, что бы лучше понять принцип действия
/*
* Функция вычисляет количество элементов,
* тем самым подготавливая параметры для первого запуска,
* и запускает сам процесс.
*/
	$left = 0;
	$right = count($array) — 1;
/*
* Функция, непосредственно производящая сортировку.
* Так как массив передается по ссылке, ничего не возвращает.
*/
function my_sort(&$array, $left, $right)
//Создаем копии пришедших переменных, с которыми будем манипулировать в дальнейшем.
$l = $left;
$r = $right;
//Вычисляем ‘центр’, на который будем опираться. Берем значение ~центральной ячейки массива.
$center = $array[(int)($left + $right) / 2];
//Цикл, начинающий саму сортировку
do
//Ищем значения больше ‘центра’
while ($array[$r] > $center) <
$r—;
>
//Ищем значения меньше ‘центра’
while ($array[$l] < $center) <
$l++;
>
//После прохода циклов проверяем счетчики циклов
if ($l
//И если условие true, то меняем ячейки друг с другом.
list($array[$r], $array[$l]) = array($array[$l], $array[$r]);
//И переводим счетчики на следующий элементы
$l++;
$r—;
>
//Повторяем цикл, если true
> while ($l
if ($r > $left) //Если условие true, совершаем рекурсию
//Передаем массив, исходное начало и текущий конец
my_sort($array, $left, $r);
>
if ($l < $right) //Если условие true, совершаем рекурсию
//Передаем массив, текущие начало и конец
my_sort($array, $l, $right);
>
Конечно же, этот алгоритм применяется во многих других языках программирования, и думаю спрашивать его могут не только на собеседованиях PHP разработчиков, потому надеюсь, я кому то помогу.