按数值排序平面关联数组,然后按键排序

问题描述 投票:0回答:8

我有一个带有数值的字符串键数组,用于创建一个标签列表,其中每个标签的出现次数与此类似:

$arrTags = [
    'mango' => 2, 
    'orange' => 4, 
    'apple' => 2,
    'banana' => 3
];

我想在列表中显示具有降序值的标签,然后 标签名称升序生成:

orange (4)  
banana (3) 
apple (2) 
mango (2)

arsort()
不合适,因为它会将
mango
放在
apple
之前。我猜
usort()
可能就是这样,但我在 php.net 的评论中没有找到合适的例子。

php sorting arrays
8个回答
42
投票

正如 Scott Saunders 在对 David 解决方案的评论中暗示的那样,您可以使用 array_keys() 和 array_values() 函数来摆脱循环。事实上,你可以用一行代码解决这个问题:

array_multisort(array_values($arrTags), SORT_DESC, array_keys($arrTags), SORT_ASC, $arrTags);

15
投票

看一下示例#3: http://php.net/manual/en/function.array-multisort.php

您需要创建两个数组用作索引;一个由原始数组的键组成,另一个由原始数组的值组成。

然后使用 multisort 按文本值(原始数组的键)排序,然后按数值(原始数组的值)排序。


15
投票

已解决

经过一些实验,我发现

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
投票

之前提出的解决方案似乎合乎逻辑,但它就是行不通:

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
投票

SlappyTheFish 是正确的:使用 array_multisort 与 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
)

1
投票
//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);

一定没问题。


1
投票

使用

uksort()
将键传递到自定义函数的范围内;在该范围内,通过使用传入(完整)数组上的键来访问关联的值。

这样做的优点是时间复杂度——这比两个单独的排序函数调用更直接,并且不需要

array_multisort()
的设置。另外,
array_multisort()
会破坏数字键(并不是提问者的键是数字)https://3v4l.org/rQak4

虽然在提出这个问题时宇宙飞船(3 向)操作员不可用,但现在可以使用,这使得现在的比较变得更容易/更清晰。

从PHP7.4开始,语法非常简洁。 (演示)

uksort($arrTags, fn($a, $b) => [$arrTags[$b], $a] <=> [$arrTags[$a], $b]);

从 PHP7.0 - PHP7.3 开始,必须使用

use()
传入主数组。 (演示)

uksort(
    $arrTags,
    function($a, $b) use ($arrTags) {
        return [$arrTags[$b], $a] <=> [$arrTags[$a], $b];
    }
);

0
投票

你想得太复杂了:

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

现在你的数组已按照你想要的方式排序了。

注意:此技术仅在 PHP7 及更高版本中可靠:https://3v4l.org/ma7ab

© www.soinside.com 2019 - 2024. All rights reserved.