Многомерный массив 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);

Должно быть хорошо.