1

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

我正在寻找一种非常高效的方法来实现下面的函数 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"}]
?>
4

3 回答 3

3

您可以将 usort 与闭包一起使用(可用 php 5.3+)

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

在 5.3 之前,您必须创建一个 sorter 函数并传递给 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 在评论中所建议的那样,您可以使用函数来返回匿名排序器函数,因此实现不会绑定到 name 属性

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

然后你可以打电话

usort($array, getSorter("name")); 
于 2013-07-17T18:15:11.770 回答
1

我运行以下命令来比较PHP 5.3 之前的方法与使用闭包函数multisort的更现代方法的速度: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;
    }

}
于 2013-07-17T20:15:33.197 回答
1

我更喜欢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>';
于 2013-07-17T21:22:07.870 回答