Многократная сортировка массива PHP - по значению, а затем по ключу? - PullRequest
21 голосов
/ 17 февраля 2010

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

$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, и мои глаза застекляются! большое спасибо !!!

Ответы [ 7 ]

34 голосов
/ 07 июля 2011

Как Скотт Сондерс намекает в своем комментарии к решению Дэвида, вы можете использовать функции array_keys () и array_values ​​(), чтобы избавиться от цикла. Фактически, вы можете решить это в одной строке кода:

array_multisort(array_values($arrTags), SORT_DESC, array_keys($arrTags), SORT_ASC, $arrTags);
15 голосов
/ 17 февраля 2010

Посмотрите на примеры № 3: http://php.net/manual/en/function.array-multisort.php

Вам нужно будет создать два массива для использования в качестве индексов; один состоит из ключей исходного массива, а другой из значений исходного массива.

Затем используйте мультисортировку для сортировки по текстовым значениям (ключам исходного массива) и затем по числовым значениям (значениям исходного массива).

14 голосов
/ 17 февраля 2010

решаемые

После небольшого эксперимента я обнаружил, что array_multisort хорошо справляется с задачей:

$tag = array(); 
$num = array();

foreach($arrTags as $key => $value){ 
$tag[] = $key; 
$num[] = $value; 
}

array_multisort($num, SORT_DESC, $tag, SORT_ASC, $arrTags);

:)

6 голосов
/ 08 июля 2011

Предыдущее предложенное решение кажется логичным, но оно просто не работает:

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);
}
?>
3 голосов
/ 08 декабря 2010

SlappyTheFish верен в отношении: использование array_multisort против 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
)
1 голос
/ 29 марта 2017
//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);

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

0 голосов
/ 17 февраля 2010

Ты слишком много думаешь:

ksort($arrTags);
arsort($arrTags);

Теперь ваш массив отсортирован так, как вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...