Здравствуйте интересный вопрос. Когда-то сталкивался с такой задачей тоже… Вот код который вам поможет:
/* * Сортировка массива по двум параметрам с помощью usort() */ function _usort_object_by_time_ms($a, $b){ // поля по которым сортировать $array = array( 'laps'=>'desc', 'time_ms'=>'asc' ); $res = 0; foreach( $array as $k=>$v ){ if( $a->$k == $b->$k ) continue; $res = ( $a->$k < $b->$k ) ? -1 : 1; if( $v=='desc' ) $res= -$res; break; } return $res; }
Здесь в $array
нужно указать ваши поля по порядку, какое первое и второе. В значениях asc и desc — это порядок сортировки…
Функция для сортировки массива с объектами
Функция на основе первого примера, с которой удобно работать.
Передаете в $array
массив объектов (можно массив массивов), указываете в $args
параметры сортировки и получаете отсортированный массив объектов.
## Сортировка объектов/массивов находящихся в массиве, по указанным полям. function sort_nested_arrays( $array, $args = array('votes' => 'desc') ){ usort( $array, function( $a, $b ) use ( $args ){ $res = 0; $a = (object) $a; $b = (object) $b; foreach( $args as $k => $v ){ if( $a->$k == $b->$k ) continue; $res = ( $a->$k < $b->$k ) ? -1 : 1; if( $v=='desc' ) $res= -$res; break; } return $res; } ); return $array; }
Пример:
$arr = array( array( 'laps' => 25, 'time_ms' => 3143413, ), array( 'laps' => 24, 'time_ms' => 3146280, ), (object) array( 'laps' => 23, 'time_ms' => 3149972, ), (object) array( 'laps' => 25, 'time_ms' => 3162714, ), ); $arr = sort_nested_arrays( $arr, array('laps' => 'desc') ); print_r( $arr ); /* Получим: Array ( [0] => Array ( [laps] => 25 [time_ms] => 3143413 ) [1] => stdClass Object ( [laps] => 25 [time_ms] => 3162714 ) [2] => Array ( [laps] => 24 [time_ms] => 3146280 ) [3] => stdClass Object ( [laps] => 23 [time_ms] => 3149972 ) ) */
Еще одни пример сортировки по нескольким полям
Допустим у нас есть массив:
Array ( [0] => 10В [1] => 5Б [2] => 9А [3] => 11А [4] => 10А [5] => 5А [6] => 10Г [7] => 9Б )
Нам нужно отсортировать его, сначала по числу в строке, а затем по букве. Делаем так:
// сортируем по порядку: числа, потом буквы usort( $val, function($a,$b){ $res = 0; // сравниваем числа $inta=intval($a); $intb=intval($b); if( $inta != $intb ){ return ( $inta > $intb ) ? 1 : -1; } // сравниваем буквы $var1 = preg_replace('~[0-9]+~', '', $a); $var2 = preg_replace('~[0-9]+~', '', $b); $compare = strcmp( $var1, $var2 ); // А считается меньше Б if( $compare !== 0 ){ return ( $compare > 0 ) ? 1 : -1; } return $res; } );
Получим:
Array ( [0] => 5А [1] => 5Б [2] => 9А [3] => 9Б [4] => 10А [5] => 10В [6] => 10Г [7] => 11А )
wp-kama.ru
Я знаю, что это старый поток, но сегодня я столкнулся с другим примером, который может выиграть от другого подхода. У меня был случай, когда я хотел использовать конкретный ключ, чтобы я мог абстрагироваться от фактической функции поддержки. Это привело к поиску версии с использованием функции-обертки для возврата анонимной функции с использованием командного слова «use» для указания имени ключа, используемого для сортировки в моем классе. (в моем случае это ключ в свойстве в [вложенном] классе, который присваивается одному из свойств класса, в котором я выполняю сортировку, то есть я сортирую экземпляры на основе свойства в экземпляре «размеры» присваивается свойство «элементов» и хочет иметь возможность сортировать их по ширине, высоте, длине или весу, например). Затем, чтобы получить свою функцию для обратного вызова, вы просто вызываете эту функцию-обертку с помощью имени ключа, которое вы хотите использовать для сортировки результата:
/** * list of items * * @var Item[] */ public $items; /** * @param string $key * @return Closure */ private static function keySort($key) { return function ($ia, $ib) use ($key) { if($ia->dimensions->$key == $ib->dimensions->$key) return 0; return ($ia->dimensions->$key < $ib->dimensions->$key) ? -1 : 1; }; } /** * return the list of items in the items array sorted by the value * of the property specified by $key * * @param string $key * @return Item[] * @throws Exception */ public function sortItemsByKey($key) { if(in_array($key, array( 'width', 'length', 'height', 'weight', ))) { return usort($this->items, static::keySort($key)); } else throw new Exception(__METHOD__ . ' invalid sort key!'); }
Это позволяет мне называть его локальным, используя либо static:: или self:: (возможно, я мог бы даже обернуть его как нестационарную функцию в этом случае, так как единственное, что меня беспокоит, — это вызов, но функция возвращена) Еще одно преимущество, которое я вскоре обнаружил, — это мой размерный объект, который также имеет некоторые «рассчитанные» поля, такие как обхват, объем и размерный вес. Но одна проблема заключается в том, что размерный вес варьируется в зависимости от того, отправляете ли вы товар внутри страны или на международном уровне, поэтому мне нужно сообщить свою функцию «calculateDimensionalWeight», если она должна использовать значение для международной доставки или нет.
, используя этот метод, я могу это сделать, просто передав дополнительный параметр функции-оболочки и добавив дополнительный параметр к переменным использования. Так как мне также необходимо убедиться, что эти значения были рассчитаны до выполнения каких-либо сравнений, я могу вызвать это в моей функции на основе ключа:
/** * @param string $key * @param bool $intl // only used for dimensional weight * @return Closure */ private static function keySort($key,$intl=false) { return function ($ia, $ib) use ($key,$intl) { switch($key) { case 'girth': $ia->dimensions->calculateGirth(); $ib->dimensions->calculateGirth(); break; case 'dimweight': $ia->dimensions->calculateDimensionalWeight($intl); $ib->dimensions->calculateDimensionalWeight($intl); break; case 'volume': $ia->dimensions->calculateVolume(); $ib->dimensions->calculateVolume(); break; } if($ia->dimensions->$key == $ib->dimensions->$key) return 0; return ($ia->dimensions->$key < $ib->dimensions->$key) ? -1 : 1; }; } /** * return the list of items in the items array sorted by the value * * @param string $key * @param bool $intl (only used for dimensional weight sorts on international shipments) * @return Item[] * @throws Exception */ public function sortItemsByKey($key,$intl=false) { if(in_array($key, array('value','collect', 'width', 'length', 'height', 'weight', 'girth', 'dimweight', 'volume'))) { return usort($this->items, static::keySort($key,$intl)); } else throw new Exception(__METHOD__ . ' invalid sort key!'); }
ПРИМЕЧАНИЕ: вычисление значений таким образом создает накладные расходы, так как все, кроме первого и последнего элементов в любом списке, будут технически вычисляться дважды, что является избыточным, но в этом случае мои списки не длинны, а в некоторых случаях мне нужно сравнить два при выполнении сортировки по ячейкам, поэтому он все же предпочтительнее. Для больших наборов данных было бы разумнее предварительно вычислять значения, внешние по отношению к методу сортировки.
qaru.site
If you've used ADO before, you may have used the Sort property on a recordset. It's very powerful - you can add a nice ORDER BY clause after getting the recordset from the database. It's especially helpful if you want to show a list on a web page and make the column headings links that cause the list to resort on that column.
I wanted to do the same thing with mysql recordsets, but it looks like you have to have the ORDER BY in your query. I re-worked the example from johan_land at yahoo dot com above for sorting multidimensional arrays. When I get a mysql recordset, I create an array with all of the records like this:
$aaRows[] = array();
if (mysql_num_rows($rsRows) > 0)
while ($aRow = mysql_fetch_array($rsRows, MYSQL_ASSOC))
$aaRows[] = $aRow;
At this point $aaRows is an array of arrays - it's a numeric-indexed array containing records from the recordset, which themselves are associative arrays. The following code takes the array of records as the first parameter, and an array of fields to sort - each field is an associative array, where 'name' is the db field name, and 'dir' is the direction to sort. If dir is 'DESC' (case-insensitive), it will sort descending. Any other value (including not setting one) will cause it to sort ascending.
function sortRows(&$a_aaRows, $a_aaSortCriteria)
{
GLOBAL $g_aaSortArray;
function compare($a_aRow1, $a_aRow2, $a_lField = 0)
{
GLOBAL $g_aaSortArray;
$lCompareVal = 0;
if ($a_lField < count($g_aaSortArray))
{
$sSortFieldName = $g_aaSortArray[$a_lField]['name'];
$sSortFieldDir = $g_aaSortArray[$a_lField]['dir'];
$vValue1 = eval('return $a_aRow1[' . $sSortFieldName . '];');
$vValue2 = eval('return $a_aRow2[' . $sSortFieldName . '];');
if ($vValue1 == $vValue2)
$lCompareVal = compare($a_aRow1, $a_aRow2, $a_lField + 1);
else
{
$lCompareVal = $vValue1 > $vValue2 ? 1 : -1;
if (strtolower(substr($sSortFieldDir, 0, 4)) == 'desc')
$lCompareVal = -$lCompareVal;
}
}
return $lCompareVal;
}
$g_aaSortArray = $a_aaSortCriteria;
usort($a_aaRows, 'compare');
}
When I call it it looks something like this:
sortRows($aaRows, array(array('name' => 'STATE', 'dir' => 'ASC'), array('name' => 'CITY', 'dir' => 'DESC')));
php.svchat.ru
<?php
/* returns the collated string (with no accent or with the matching string
* replacement) in lower case according to that language rule.
* The aim is to alphabetically sort lists of strings with characters from
* other languages but using collation rules of that given language
* (ISO 639-1 code).
* Latin-derived alphabets are supported (currently English, French and
* German)
* rules source: http://en.wikipedia.org/wiki/Latin_alphabet
*/
function collatedLower($string, $lang=null) {
switch ($lang) {
case 'de':
// German
/*
* In German, letters with umlaut (Ä, Ö, Ü) are treated generally
* just like their non-umlauted versions; ß is always sorted as ss.
* This makes the alphabetic order Arg, Ärgerlich, Arm, Assistent,
* Aßlar, Assoziation.
* For phone directories and similar lists of names, the umlauts are
* to be collated like the letter combinations "ae", "oe", "ue".
* This makes the alphabetic order Udet, Übelacker, Uell, Ülle, Ueve,
* .
grave;|ê|ë|É|È|Ê|Ë/",
"/ì|í|î|ï|Ì|Í|Î|Ï/",
"/ñ|Ñ/",
"/ò|ó|ô|õ|ø|Ò|Ó|Ô|Õ|Ø/",
"/ö|œ|Ö|Œ/",
"/ß/",
"/ù|ú|û|Ù|Ú|Û/",
"/ü|Ü/",
"/ý|ÿ|Ý/");
$replace = array('a', 'ae', 'c', 'e', 'i', 'n', 'o', 'oe', 'ss', 'u', 'ue', 'y');
break;
default:
// 'en' (English), 'fr' (French)
/*
* In French and English, characters with diaeresis (ä, ë, ï, ö, ü, ÿ)
* are usually treated just like their un-accented versions.
* The ligatures Æ, Œ, and the symbol ß, when used in English, French,
* or German, are normally not counted as separate alphabe.
> */
$patterns = array("/à|á|â|ã|ä|å|À|Á|Â|Ã|Ä|Å/",
"/æ|Æ/",
"/ç|Ç/",
"/é|è|ê|ë|É|È|Ê|Ë/",
"/ì|í|î|ï|Ì|Í|Î|Ï/",
"/ñ|Ñ/",
"/ò|ó|ô|õ|ö|ø|Ò|Ó|Ô|Õ|Ö|Ø/",
"/œ|Œ/",
"/ß/",
"/ù|ú|û|ü|Ù|Ú|Û|Ü/",
"/ý|ÿ|Ý/");
$replace = array('a', 'ae', 'c', 'e', 'i', 'n', 'o', 'oe', 'ss', 'u', 'y');
break;
}
return preg_replace($patterns,$replace,$string);
}
// English
function compareAccents_en($a, $b) {
return compareAccents($a, $b, 'en');
}
// French
function compareAccents_fr($a, $b) {
return compareAccents($a, $b, 'fr');
}
// German
function compareAccents_de($a, $b) {
return compareAccents($a, $b, 'de');
}
/*
* comparison function to group together accented letters with their lower-case
* non-accented counterparts
* the $lang parameter enables sorting rules for that language (ISO 639-1 code)
*/
function compareAccents($a, $b, $lang=null) {
$anew = strtolower(collatedLower($a,$lang));
$bnew = strtolower(collatedLower($b,$lang));
if ($anew < $bnew) return -1;
if ($anew > $bnew) return 1;
return 0;
}
// usage:
usort($myList,'compareAccents_fr');
// to be compared to:
setlocale(LC_COLLATE,'fr');
usort($myList, 'strcoll');
?>
www.navioo.com