Этот вопрос отличается от других, поскольку основное внимание уделяется сортировке массива со статическим классом, а не типичным процедурным подходом.
Я ищу очень эффективный способ реализации функции 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"}] ?>
Я multisort
следующее, чтобы сравнить скорость multisort
, метод pre-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; } }
Вы можете использовать usort с закрытием (Available php 5.3+)
usort($array, function($a, $b){ return strcmp($a["name"], $b["name"]);});
Pre 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 в комментариях, вы можете использовать функцию для возврата анонимной функции сортировщика, чтобы реализация не привязана к свойству name
function getSorter($property){ return function($a, $b) use ($property){ return strcmp($a[$property], $b[$property]); }; }
Затем вы можете позвонить
usort($array, getSorter("name"));
Я предпочитаю 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>';