Многомерный массив PHP – по значению, затем по ключу?

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

$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); 

Должно быть, все в порядке.