Многомерный массив 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, и мои глаза затуманиваются! большое спасибо!!!
Ответы
Ответ 1
Взгляните на примеры № 3:
http://php.net/manual/en/function.array-multisort.php
Вам нужно создать два массива для использования в качестве индексов; один из которых состоит из исходных ключей массива, а другой - из исходных значений массива.
Затем используйте multisort для сортировки по текстовым значениям (ключи исходного массива), а затем по числовым значениям (значения исходного массива).
Ответ 2
Как говорит Скотт Сондерс в своем комментарии к решению Дэвида, вы можете использовать функции array_keys() и array_values (), чтобы избавиться от цикла. Фактически, вы можете решить это в одной строке кода:
array_multisort(array_values($arrTags), SORT_DESC, array_keys($arrTags), SORT_ASC, $arrTags);
Ответ 3
решаемые
После небольшого эксперимента я обнаружил, что array_multisort
делает трюк красиво:
$tag = array();
$num = array();
foreach($arrTags as $key => $value){
$tag[] = $key;
$num[] = $value;
}
array_multisort($num, SORT_DESC, $tag, SORT_ASC, $arrTags);
:)
Ответ 4
Предыдущее предлагаемое решение кажется логичным, но оно просто не работает:
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);
}
?>
Ответ 5
SlappyTheFish верен: с помощью array_multisort vs ksort, arsort
В примере David 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
)
Ответ 6
Я не пробовал, но попробовали ли сортировку по возрастанию в первую очередь, а затем сортировку значений по убыванию?
Кажется, что большинство видов не будут перемещать элементы, если они уже одинаковы.
Ответ 7
Вы можете просто создать функцию для создания пустого массива и вставить их в порядке, основанном на сравнении.
Ответ 8
Вы думаете слишком сложно:
ksort($arrTags);
arsort($arrTags);
Теперь ваш массив отсортирован так, как вы хотите.
Ответ 9
//preserve arrays keys for later use
$ar1= array_keys($your_array);
//preserve array 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);
Должно быть хорошо.