У меня есть массив строковых ключей с числовыми значениями для использования в списке тегов с количеством событий каждого тега, таким образом:
$arrTags['mango'] = 2; $arrTags['orange'] = 4; $arrTags['apple'] = 2; $arrTags['banana'] = 3;
это значит, что я могу отобразить список тегов в порядке убывания, таким образом:
orange (4) banana (3) mango (2) apple (2)
я могу использовать arsort для сортировки по значению, которое является блестящим, но я также хочу, чтобы любые теги, которые имеют одинаковое числовое значение, сортируются в алфавитном порядке, поэтому конечным результатом может быть:
orange (4) banana (3) apple (2) mango (2)
есть ли способ, которым я могу это сделать? Я предполагаю, что usort может быть путем, но я смотрю на примеры на php.net, и мои глаза затуманиваются! большое спасибо!!!
Взгляните на примеры # 3: http://php.net/manual/en/function.array-multisort.php
Вам нужно создать два массива для использования в качестве индексов; один из которых состоит из ключей исходного массива и других значений исходного массива.
Затем используйте multisort для сортировки по текстовым значениям (ключи исходного массива), а затем по числовым значениям (значения исходного массива).
Как Скотт Сондерс намекает в своем комментарии к решению Дэвида, вы можете использовать функции array_keys () и array_values (), чтобы избавиться от цикла. Фактически, вы можете решить это в одной строке кода:
array_multisort(array_values($arrTags), SORT_DESC, array_keys($arrTags), SORT_ASC, $arrTags);
РЕШИТЬ
После небольшого эксперимента я обнаружил, что array_multisort
делает трюк красиво:
$tag = array(); $num = array(); foreach($arrTags as $key => $value){ $tag[] = $key; $num[] = $value; } array_multisort($num, SORT_DESC, $tag, SORT_ASC, $arrTags);
🙂
Предыдущее предлагаемое решение кажется логичным, но оно просто не работает:
ksort($arrTags); arsort($arrTags);
Полный PHP-код для реализации заданной сортировки будет:
$k = array_keys($arrTags); $v = array_values($arrTags); array_multisort($k, SORT_ASC, $v, SORT_DESC); $arrTags = array_combine($k, $v);
Обратите внимание, что array_multisort () использует ссылки на пользовательский ввод, поэтому вам придется использовать два временных переменных ($ k и $ v) для подачи контента в качестве пользовательского ввода. Таким образом array_multisort () может изменить содержимое. Позже, перестройте отсортированный массив через array_combine ().
Я создал функцию повторного использования для выполнения этой задачи:
<?php /** * Sort a multi-dimensional array by key, then by value. * * @param array Array to be sorted * @param int One of the available sort options: SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING * @param int One of the available sort options: SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING * @return void * @example The following array will be reordered: * $a = array( * 'd' => 4, * 'c' => 2, * 'a' => 3, * 'b' => 1, * 'e' => 2, * 'g' => 2, * 'f' => 2, * ); * SortArrayByKeyThanValue($a); # reorder array to: array( * 'b' => 1, * 'c' => 2, * 'e' => 2, * 'f' => 2, * 'g' => 2, * 'a' => 3, * 'd' => 4, * ); * @author Sijmen Ruwhof <sijmen(a)secundity.com> * @copyright 2011, Secundity */ function SortArrayByKeyThanValue (&$pArray, $pSortMethodForKey = SORT_ASC, $pSortMethodForValue = SORT_ASC) { # check user input: sorting is not necessary if (count($pArray) < 2) return; # define $k and $v as array_multisort() needs real variables, as user input is put by reference $k = array_keys ($pArray); $v = array_values($pArray); array_multisort( $v, $pSortMethodForValue, $k, $pSortMethodForKey ); $pArray = array_combine($k, $v); } ?>
SlappyTheFish верен: с помощью array_multisort vs ksort, arsort
В примере Дэвида ksort arsort работает отлично, однако, если строковые значения ключей содержат символы, отличные от буквенных символов, сортировка может не работать должным образом.
например:
$arrTags['banana'] = 3; $arrTags['mango'] = 2; $arrTags['apple1'] = 2; $arrTags['orange'] = 4; $arrTags['almond1'] = 2; ksort($arrTags); arsort($arrTags); print_r($arrTags);
возвращает:
Array ( [orange] => 4 [banana] => 3 [apple1] => 2 [mango] => 2 [almond1] => 2 )
однако используя:
$arrTags['banana'] = 3; $arrTags['mango'] = 2; $arrTags['apple1'] = 2; $arrTags['orange'] = 4; $arrTags['almond1'] = 2; $tag = array(); $num = array(); foreach($arrTags as $key => $value){ $tag[] = $key; $num[] = $value; } array_multisort($num, SORT_DESC, $tag, SORT_ASC, $arrTags); print_r($arrTags);
возвращает:
Array ( [orange] => 4 [banana] => 3 [almond1] => 2 [apple1] => 2 [mango] => 2 )
Я не пробовал это, но попробовал ли вы сначала сортировать ключи по возрастанию, а затем сортировать значения по убыванию?
Кажется, что большинство сортов не будет перемещать элементы вокруг, если они уже одинаковы.
Вы можете просто создать функцию для создания пустого массива и вставить их в порядке, основанном на сравнении.
Вы думаете слишком сложно:
ksort($arrTags); arsort($arrTags);
Теперь ваш массив отсортирован так, как вы этого хотите.
//preserve arrays keys for later use $ar1= array_keys($your_array); //preserve array's values for later use $ar2= array_values($your_array); //perform sorting by value and then by key array_multisort($ar2, SORT_DESC, $ar1, SORT_DESC); //combine sorted values and keys arrays to new array $sorted_array = array_combine($ar1, $ar2);
Должно быть, все в порядке.