在PHP中使用静态类方法*快速*按键值对数组进行排序


Using a Static Class Method to *Quickly* Sort an Array By Key Value in PHP

这个问题与其他问题不同,因为它的重点是使用静态类方法而不是典型的过程方法对数组进行排序。

我正在寻找一种非常高效的方式来实现下面的函数sortByKeyValue。其他一些相关的答案都集中在完成工作上,这个问题更多的是关于完成工作并快速完成(作为一种静态方法)。

有人想试试吗?我可能会在这个问题上慷慨解囊,以挤出表演迷

<?php
$data = array(
   array('name' => 'B', 'cheesy' => 'bacon'),
   array('name' => 'C', 'delicious' => 'tacos'),
   array('name' => 'A', 'lovely' => 'viddles'),
);
class MyArray {
    public static function sortByKeyValue($array, $key, $direction = 'ASC') {
        // Do the thing
        // Help me!
        return $array;
    }
}
$data = MyArray::sortByKeyValue($data, 'name');
// Should output the name key in order
// I am not including the garbage keys I threw in, but they should be there too)
// [{"name": "A"},{"name": "B"},{"name": "C"}]
?>

您可以使用带有闭包的usort(可用php 5.3+)

 usort($array, function($a, $b){ return strcmp($a["name"], $b["name"]);});

在5.3之前,您必须创建一个分拣机功能并将其传递给usort

 function arraySorter($a, $b){
     return strcmp($a["name"], $b["name"]);
 }
 usort($array, "arraySorter");

或者,您可以将arraySorter作为静态方法放置在类上

 public static function _arraySorter($a, $b){
     return strcmp($a["name"], $b["name"]); 
 }
 // then call
 usort($array, array("MyArray", "_arraySorter")); // for static 

注意。这将执行就地排序。

正如@Kirk在评论中建议的那样,你可以使用一个函数来返回一个匿名分类器函数,这样实现就不会绑定到名称属性

function getSorter($property){
       return function($a, $b) use ($property){
           return strcmp($a[$property], $b[$property]);
       };
}

然后你可以打电话给

usort($array, getSorter("name")); 

我运行了以下内容来比较multisort(一种PHP 5.3之前的方法)和一种使用usort和闭包函数的更现代的方法的速度:

$alpha = 'abcdefghijklmnopqrstuvwxyz';
$cnt = 1000;
$key = 'name';
$direction = 'ASC';
$array = array();
for ($i=0; $i<$cnt; $i++){
    $array[$i]['name'] = substr(str_shuffle($alpha), 0, 8);
    $array[$i]['job'] = substr(str_shuffle($alpha), 0, 8);
}
$pre = $array;//the test dummies
//PRE-PHP 5.3
$t[0] = -microtime();
$sub = array();
foreach ($pre as $item) {
        $sub[] = $item[$key];
}
if ($direction == 'ASC') $ord = SORT_ASC;
else $ord = SORD_DESC;
array_multisort($sub, $ord, $pre);
$t[0] += microtime();
//USORT WITH CLOSURE
$t[1] = -microtime();
usort($array, function ($a, $b) use($key, $direction){
    if ($direction == 'ASC'){
        return strcmp($a[$key], $b[$key]);
    }
    return strcmp($b[$key], $a[$key]);
});
$t[1] += microtime();
var_dump($t);

正如你所看到的,旧方法的速度是原来的两倍多:

Array
(
    [0] => 0.005
    [1] => 0.014001
)

下面是我上课的方法:

class MyArray {
    public static function sortByKeyValue($array, $key, $direction = SORT_ASC) {
        $sub = array();
        foreach ($array as $item) {
            $sub[] = $item[$key];
        }
        array_multisort($sub, $direction, $array);
        return $array;
    }
}

我更喜欢array_multisort():

<?php
$data = array(
   array('name' => 'B', 'cheesy' => 'bacon'),
   array('name' => 'C', 'delicious' => 'tacos'),
   array('name' => 'A', 'lovely' => 'viddles'),
);
class MyArray {
    public static function sortByKeyValue($array, $key, $direction = 'ASC') {
        $tmp = array();
        foreach($array as $k=>$r){
            $tmp[] = $r[$key];
        }
        array_multisort($tmp,($direction == 'ASC' ? SORT_ASC : SORT_DESC),$array);
        return $array;
    }
}
$data = MyArray::sortByKeyValue($data, 'name');
echo '<pre>',print_r($data),'</pre>';