PHP,按密钥长度排序数组&值

时间:2011-12-21 20:55:46

标签: php

完成的数组看起来像这样:

array(

'foo bar bar foo' => 10,
'foo' => 10,
'foo bar bar bar foo' => 6,
'foo bar' => 6,
'bar' => 6,
'b' => 5

)

因此,值首先按值排序,然后按键的长度排序。

在MySQL中我会这样做:

SELECT product, qty FROM stock ORDER BY qty DESC, LENGTH(product) DESC 

但我想用PHP来做。

5 个答案:

答案 0 :(得分:3)

看一下php的usortuasort

你应该能够定义一个可以像那样排序的函数

不确定它是否能够轻松地与当前阵列一起使用,但是这个

$array = array(
 array('name' => 'foo bar bar foo', 'qty' => 10 ),
 array('name' => 'foo', 'qty' => 6),
 array('name' => 'foo bar bar foo', 'qty' => 6 ),
 array('name' => 'foo bar', 'qty' => 6 )
);

uasort($array, 'arraySort');

function arraySort($a, $b)
{
    if($a['qty'] > $b['qty'])
        return 1;
    elseif($a['qty'] < $b['qty'])
        return -1;
    else
        if(strlen($a['name']) >= strlen($b['name']))
            return 1;
        else
            return -1;
}

答案 1 :(得分:3)

查看此问题的答案:PHP array multiple sort - by value then by key?,似乎array_multisort是要走的路。 (我不确定array_multisort是如何工作的,我只是把它搞砸了,而且似乎有用了。)

试试这个:

$arr = array(
  'foo bar' => 6,
  'foo' => 10,
  'bar' => 6,
  'b' => 5,
  'foo bar bar bar foo' => 6,
  'foo bar bar foo' => 10
);

array_multisort(array_values($arr), SORT_DESC,
  array_map(create_function('$v', 'return strlen($v);'), array_keys($arr)),
  SORT_DESC, $arr);

演示:http://codepad.org/mAttNIV7

更新:添加array_map以使其按字符串的长度排序,然后再进行操作:

$str1 > $str2代替strlen($str1) > strlen($str2)

更新2:在PHP&gt; = 5.3中,您可以使用真正的匿名函数替换create_function

array_map(function($v){return strlen($v);}, array_keys($arr))

演示2:http://codepad.viper-7.com/6qrFwj

答案 2 :(得分:0)

基于长度对键进行排序时的一个限制是:不重新排序等长键。假设我们需要按descending顺序按长度订购密钥。

$arr = array(
    "foo 0" => "apple",
    "foo 1" => "ball",
    "foo 2 foo 0 foo 0" => "cat",
    "foo 2 foo 0 foo 1 foo 0" => "dog",
    "foo 2 foo 0 foo 1 foo 1" => "elephant",
    "foo 2 foo 1 foo 0" => "fish",
    "foo 2 foo 1 foo 1" => "giraffe"
);

debug($arr, "before sort");
$arrBad = $arr;
sortKeysDescBAD($arrBad);
debug($arrBad, "after BAD sort");
sortKeysDescGOOD($arr);
debug($arr, "after GOOD sort 2");

function sortKeysDescBAD(&$arrNew) {
    $arrKeysLength = array_map('strlen', array_keys($arrNew));
    array_multisort($arrKeysLength, SORT_DESC, $arrNew);
    //return max($arrKeysLength);
}

function sortKeysDescGOOD(&$arrNew) {
    uksort($arrNew, function($a, $b) {
        $lenA = strlen($a); $lenB = strlen($b);
        if($lenA == $lenB) {
            // If equal length, sort again by descending
            $arrOrig = array($a, $b);
            $arrSort = $arrOrig;
            rsort($arrSort);
            if($arrOrig[0] !== $arrSort[0]) return 1;
        } else {
            // If not equal length, simple
            return $lenB - $lenA;
        }
    });
}

function debug($arr, $title = "") {
    if($title !== "") echo "<br/><strong>{$title}</strong><br/>";
    echo "<pre>"; print_r($arr); echo "</pre><hr/>";
}

输出将是:

before sort
Array
(
    [foo 0] => apple
    [foo 1] => ball
    [foo 2 foo 0 foo 0] => cat
    [foo 2 foo 0 foo 1 foo 0] => dog
    [foo 2 foo 0 foo 1 foo 1] => elephant
    [foo 2 foo 1 foo 0] => fish
    [foo 2 foo 1 foo 1] => giraffe
)

after BAD sort
Array
(
    [foo 2 foo 0 foo 1 foo 0] => dog
    [foo 2 foo 0 foo 1 foo 1] => elephant
    [foo 2 foo 0 foo 0] => cat
    [foo 2 foo 1 foo 0] => fish
    [foo 2 foo 1 foo 1] => giraffe
    [foo 0] => apple
    [foo 1] => ball
)

after GOOD sort
Array
(
    [foo 2 foo 0 foo 1 foo 1] => elephant
    [foo 2 foo 0 foo 1 foo 0] => dog
    [foo 2 foo 1 foo 1] => giraffe
    [foo 2 foo 1 foo 0] => fish
    [foo 2 foo 0 foo 0] => cat
    [foo 1] => ball
    [foo 0] => apple
)

请注意两个排序方法中elephantdog的顺序(例如(或其他))。第二种方法看起来更好。可能有更简单的方法来解决这个问题,但希望这有助于某些人......

答案 3 :(得分:0)

从类似于sql结果集的输入数组开始,您可以干净地使用usort(),它包含三向比较,然后有条件地进行辅助三向比较。完成后,您可以将qty列的数据作为值隔离,并且(假设所有name的值都是唯一的)使用name列作为使用{{1} }。比较时,将array_column()数据写在运算符的左侧,将$b写在右侧,以实现降序排列。

代码:(Demo

$a

输出:

$array = [
    ['name' => 'foo bar bar foo', 'qty' => 6],
    ['name' => 'bah', 'qty' => 5],
    ['name' => 'foo foo bar foo', 'qty' => 10],
    ['name' => 'foo', 'qty' => 6],
    ['name' => 'foo bar', 'qty' => 6],
    ['name' => 'bar', 'qty' => 11],
];

usort($array, function($a, $b) {
    return $b['qty'] <=> $a['qty'] ?: strlen($b['name']) <=> strlen($a['name']);
});

var_export(array_column($array, 'qty', 'name'));

使用array ( 'bar' => 11, 'foo foo bar foo' => 10, 'foo bar bar foo' => 6, 'foo bar' => 6, 'foo' => 6, 'bah' => 5, ) 的优势在于,除非有必要进行平局决胜,否则comparison1 ?: comparison2中的函数调用不会执行-这样可以提高效率。另外,使用comparison2将无条件地对所有array_multisort()值调用strlen() -即使它们不需要进行排序。

使用单个太空飞船操作员执行排序是完全有效的,但是以下技术将在每次进行比较时进行两个函数调用。这将比上面的代码段效率低,因此我不推荐以下代码段

qty

p.s。当然,usort($array, function($a, $b) { return [$b['qty'], strlen($b['name']] <=> [$a['qty'], strlen($a['name'])]; }); 也可以做到这一点,我只是觉得语法不太简洁。

array_multisort()

答案 4 :(得分:-2)

在php中使用sort函数。确保使用TRUE作为第二个参数来保存密钥。