我怎样才能sorting在PHP中的数组和数据?
由于“我如何分类我的独特雪花arrays”这个巨大而又重复的数量? 问题,这是PHP中基本sorting方法的参考集合。 请closures任何与本文无重复区别的问题。
我如何sorting在PHP中的数组?
如何在PHP中sorting复杂的数组?
我如何sorting在PHP中的对象数组?
-
基本的一维数组; 含。 multidimensional array,包括 对象数组; 含。 基于另一个sorting一个数组
-
用SPLsorting
-
稳定的sorting
有关使用PHP现有函数的实际答案,请参阅1.有关sortingalgorithm的学术性详细答案(PHP的函数实现以及您可能需要哪些实际上非常复杂的情况),请参阅2。
那么大多数基本的方法已经被欺骗覆盖,我会尝试看看其他types的sorting
用SPLsorting
SplHeap
class SimpleHeapSort extends SplHeap { public function compare($a, $b) { return strcmp($a, $b); } } // Let's populate our heap here (data of 2009) $heap = new SimpleHeapSort(); $heap->insert("a"); $heap->insert("b"); $heap->insert("c"); echo implode(PHP_EOL, iterator_to_array($heap));
产量
c b a
SplMaxHeap
SplMaxHeap类提供堆的主要function,保持最大值。
$heap = new SplMaxHeap(); $heap->insert(1); $heap->insert(2); $heap->insert(3);
SplMinHeap
SplMinHeap类提供了堆的主要function,保持最小值。
$heap = new SplMinHeap (); $heap->insert(3); $heap->insert(1); $heap->insert(2);
其他types的sorting
泡沫sorting
从维基百科关于泡泡的文章sorting:
冒泡sorting,有时被错误地称为沉没sorting,是一种简单的sortingalgorithm,它通过反复遍历列表进行sorting,比较每对相邻的项目,如果sorting错误,则交换它们。 重复列表直到不需要交换,这表明列表已经sorting。 algorithm的名字来自于小的元素“泡泡”到列表的顶部。 因为它只使用比较操作元素,所以这是一个比较sorting。 虽然algorithm很简单,但大多数其他sortingalgorithm对于大型列表来说效率更高。
function bubbleSort(array $array) { $array_size = count($array); for($i = 0; $i < $array_size; $i ++) { for($j = 0; $j < $array_size; $j ++) { if ($array[$i] < $array[$j]) { $tem = $array[$i]; $array[$i] = $array[$j]; $array[$j] = $tem; } } } return $array; }
selectsorting
从维基百科文章selectsorting:
在计算机科学中,selectsorting是一种sortingalgorithm,特别是就地比较sorting。 它具有O(n2)的时间复杂度,使其在大型列表上效率低下,并且通常比类似的插入sorting更差。 selectsorting因其简单性而被注意到,并且在某些情况下,特别是在辅助存储器有限的情况下,其具有比更复杂algorithm的性能优势。
function selectionSort(array $array) { $length = count($array); for($i = 0; $i < $length; $i ++) { $min = $i; for($j = $i + 1; $j < $length; $j ++) { if ($array[$j] < $array[$min]) { $min = $j; } } $tmp = $array[$min]; $array[$min] = $array[$i]; $array[$i] = $tmp; } return $array; }
插入sorting
从维基百科关于插入sorting的文章:
插入sorting是一种简单的sortingalgorithm,一次构build最终的sorting数组(或列表)。 在较大的列表上,这比快速sorting,堆sorting或合并sorting等更高级的algorithm效率低得多。 但是,插入sorting提供了几个优点:
function insertionSort(array $array) { $count = count($array); for($i = 1; $i < $count; $i ++) { $j = $i - 1; // second element of the array $element = $array[$i]; while ( $j >= 0 && $array[$j] > $element ) { $array[$j + 1] = $array[$j]; $array[$j] = $element; $j = $j - 1; } } return $array; }
希尔sorting
从维基百科上的Shellsort文章:
壳牌,也被称为壳牌sorting或壳牌的方法,是一个就地比较sorting。 它通过开始比较和交换与相邻元素完成之前相距甚远的元素的交换sorting,如插入或冒泡sorting。
function shellSort(array $array) { $gaps = array( 1, 2, 3, 4, 6 ); $gap = array_pop($gaps); $length = count($array); while ( $gap > 0 ) { for($i = $gap; $i < $length; $i ++) { $tmp = $array[$i]; $j = $i; while ( $j >= $gap && $array[$j - $gap] > $tmp ) { $array[$j] = $array[$j - $gap]; $j -= $gap; } $array[$j] = $tmp; } $gap = array_pop($gaps); } return $array; }
梳理sorting
来自维基百科有关梳状sorting的文章:
梳理sortingalgorithm是一种相对简单的sortingalgorithm,最初由Wlodzimierz Dobosiewicz于1980年devise,后来在1991年由Stephen Lacey和Richard Box重新发现。梳理sorting改善了气泡sorting。
function combSort(array $array) { $gap = count($array); $swap = true; while ( $gap > 1 || $swap ) { if ($gap > 1) $gap /= 1.25; $swap = false; $i = 0; while ( $i + $gap < count($array) ) { if ($array[$i] > $array[$i + $gap]) { // swapping the elements. list($array[$i], $array[$i + $gap]) = array( $array[$i + $gap], $array[$i] ); $swap = true; } $i ++; } } return $array; }
合并sorting
从合并sorting的维基百科文章:
在计算机科学中,合并sorting(通常拼写合并sorting)是基于比较的O(n log n)sortingalgorithm。 大多数实现产生一个稳定的sorting,这意味着实现保留sorting输出中的相等元素的input顺序
function mergeSort(array $array) { if (count($array) <= 1) return $array; $left = mergeSort(array_splice($array, floor(count($array) / 2))); $right = mergeSort($array); $result = array(); while ( count($left) > 0 && count($right) > 0 ) { if ($left[0] <= $right[0]) { array_push($result, array_shift($left)); } else { array_push($result, array_shift($right)); } } while ( count($left) > 0 ) array_push($result, array_shift($left)); while ( count($right) > 0 ) array_push($result, array_shift($right)); return $result; }
快速sorting
从维基百科关于Quicksort的文章:
快速sorting或分区交换sorting是托尼·霍尔(Tony Hoare)开发的一种sortingalgorithm,平均而言,它使O(n log n)比较来sortingn个项目。 在最坏的情况下,它使得O(n2)比较,尽pipe这种行为是罕见的。
function quickSort(array $array) { if (count($array) == 0) { return $array; } $pivot = $array[0]; $left = $right = array(); for($i = 1; $i < count($array); $i ++) { if ($array[$i] < $pivot) { $left[] = $array[$i]; } else { $right[] = $array[$i]; } } return array_merge(quickSort($left), array( $pivot ), quickSort($right)); }
排列sorting
从维基百科关于排列的文章sorting:
置换sorting,通过生成input数组/列表的可能排列直到发现sorting排列。
function permutationSort($items, $perms = array()) { if (empty($items)) { if (inOrder($perms)) { return $perms; } } else { for($i = count($items) - 1; $i >= 0; -- $i) { $newitems = $items; $newperms = $perms; list($foo) = array_splice($newitems, $i, 1); array_unshift($newperms, $foo); $res = permutationSort($newitems, $newperms); if ($res) { return $res; } } } } function inOrder($array) { for($i = 0; $i < count($array); $i ++) { if (isset($array[$i + 1])) { if ($array[$i] > $array[$i + 1]) { return False; } } } return True; }
基数sorting
从维基百科关于基数sorting的文章:
在计算机科学中,基数sorting是一种非比较性的整数sortingalgorithm,它通过将键组合成具有相同重要位置和值的个别数字,用整数键sorting数据。
// Radix Sort for 0 to 256 function radixSort($array) { $n = count($array); $partition = array(); for($slot = 0; $slot < 256; ++ $slot) { $partition[] = array(); } for($i = 0; $i < $n; ++ $i) { $partition[$array[$i]->age & 0xFF][] = &$array[$i]; } $i = 0; for($slot = 0; $slot < 256; ++ $slot) { for($j = 0, $n = count($partition[$slot]); $j < $n; ++ $j) { $array[$i ++] = &$partition[$slot][$j]; } } return $array; }
基本的一维数组
$array = array(3, 5, 2, 8);
适用的sortingfunction:
-
sort
-
rsort
-
asort
-
arsort
-
natsort
-
natcasesort
-
ksort
-
krsort
它们之间的区别仅仅在于是否保留键值关联(“ a
”函数),是sorting低位还是反向(“ r
”),是sorting值还是键(“ k
”),以及它比较值(“ nat
”与正常值)。 请参阅http://php.net/manual/en/array.sorting.php以获得更多信息和链接。;
multidimensional array,包括对象数组
$array = array( array('foo' => 'bar', 'baz' => 42), array('foo' => ..., 'baz' => ...), ... );
如果要通过每个条目的“foo”键对$array
进行sorting,则需要自定义比较函数 。 上面的sort
和相关函数使用简单的值,他们知道如何比较和sorting。 PHP并不是简单地“知道”如何处理一个复杂的值,如array('foo' => 'bar', 'baz' => 42)
所以你需要告诉它。
要做到这一点,你需要创build一个比较function 。 该函数采用两个元素,如果这些元素被认为是相等的,则返回0
如果第一个值较低,则该值低于0
如果第一个值较高,则该值高于0
。 这就是所需要的:
function cmp(array $a, array $b) { if ($a['foo'] < $b['foo']) { return -1; } else if ($a['foo'] > $b['foo']) { return 1; } else { return 0; } }
通常,你会想要使用匿名函数作为callback。 如果您想使用方法或静态方法,请参阅在PHP中指定callback的其他方法 。
然后您使用这些function之一:
-
usort
-
uasort
-
uksort
同样,它们只是在保持键值关联和按值或键sorting上有所不同。 阅读他们的文件的细节。
用法示例:
usort($array, 'cmp');
usort
将从数组中取两个项目,并调用你的cmp
函数。 所以cmp()
将以$a
作为array('foo' => 'bar', 'baz' => 42)
和$b
作为另一个array('foo' => ..., 'baz' => ...)
。 该函数然后返回到哪个值更大或是否相等。 usort
重复这个过程,为$a
和$b
传递不同的值,直到数组被sorting。 cmp
函数将被调用多次, 至less与$array
的值一样多,每次$a
和$b
的值的不同组合。
要习惯这个想法,试试这个:
function cmp($a, $b) { echo 'cmp called with $a:', PHP_EOL; var_dump($a); echo 'and $b:', PHP_EOL; var_dump($b); }
你所做的只是定义一个自定义的方式来比较两个项目,这就是你所需要的。 这与各种价值观一起工作。
顺便说一句,这对任何值的作品,值不一定是复杂的数组。 如果你想要做一个自定义的比较,你也可以用一个简单的数字来完成。
通过引用sort
sorting,不返回任何有用的东西!
请注意,数组sorting,您不需要将返回值分配给任何东西。 $array = sort($array)
将用true
replace数组,而不是用sorting后的数组。 刚刚sort($array);
作品。
自定义数字比较
如果你想通过baz
键(数字键)进行sorting,你所要做的就是:
function cmp(array $a, array $b) { return $a['baz'] - $b['baz']; }
由于math运算的原因,根据$a
是否小于,等于或大于$b
,返回值<0,0或> 0。
请注意,这将不适用于float
值,因为它们将减less到一个int
并失去精度。 改用显式的-1
和1
返回值。
对象
如果你有一个对象数组,它的工作原理是一样的:
function cmp($a, $b) { return $a->baz - $b->baz; }
function
你可以在比较函数中做任何你需要的事情,包括调用函数:
function cmp(array $a, array $b) { return someFunction($a['baz']) - someFunction($b['baz']); }
string
第一个string比较版本的快捷方式:
function cmp(array $a, array $b) { return strcmp($a['foo'], $b['foo']); }
strcmp
在这里完全符合cmp
,它返回-1
或1
。
太空船操作员
PHP 7引入了飞船运营商 ,它统一和简化了不同types之间的比较/等于/小于/大于等于:
function cmp(array $a, array $b) { return $a['foo'] <=> $b['foo']; }
按多个字段sorting
如果你想主要由foo
进行sorting,但是如果foo
对于两个元素是相等的,按baz
sorting:
function cmp(array $a, array $b) { if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) { return $cmp; } else { return $a['baz'] - $b['baz']; } }
对于那些熟悉的,这相当于一个ORDER BY foo, baz
的SQL查询。
另请参阅这个非常简洁的速记版本,以及如何为任意数量的键dynamic创build这样一个比较函数 。
sorting成手动,静态的顺序
如果要将元素sorting为“手动sorting”,如“foo”,“bar”,“baz” :
function cmp(array $a, array $b) { static $order = array('foo', 'bar', 'baz'); return array_search($a['foo'], $order) - array_search($b['foo'], $order); }
对于上述所有内容,如果您使用PHP 5.3或更高版本(而且您确实应该),则使用匿名函数来缩短代码,并避免使用另一个全局函数:
usort($array, function (array $a, array $b) { return $a['baz'] - $b['baz']; });
这就是对一个复杂的multidimensional array进行sorting的简单方法。 同样,只要从教PHP的angular度思考如何判断哪两个项目是“更大”的 ; 让PHP做实际的sorting。
同样对于上面的所有内容,要在升序和降序之间切换,只需交换$a
和$b
参数即可。 例如:
return $a['baz'] - $b['baz']; // ascending return $b['baz'] - $a['baz']; // descending
基于另一个sorting一个数组
然后还有一个奇怪的array_multisort
,它可以让你根据另一个sorting一个数组:
$array1 = array( 4, 6, 1); $array2 = array('a', 'b', 'c');
预期的结果是:
$array2 = array('c', 'a', 'b'); // the sorted order of $array1
使用array_multisort
来到那里:
array_multisort($array1, $array2);
如果您有更常见的情况,请随时编辑此答案。
稳定的sorting
假设你有一个这样的数组:
['Kale', 'Kaleidoscope', 'Aardvark', 'Apple', 'Leicester', 'Lovely']
现在你只想对第一个字母进行sorting:
usort($array, function($a, $b) { return strcmp($a[0], $b[0]); });
结果是这样的:
['Apple', 'Aardvark', 'Kale', 'Kaleidoscope', 'Lovely', 'Leicester']
sorting不稳定!
敏锐的观察者可能已经注意到,数组sortingalgorithm(QuickSort)没有产生稳定的结果,并且没有保留相同首字母之间的原始顺序。 这个例子是微不足道的,我们应该比较整个string,但是假设你的用例比较复杂,比如连续两次在不同的字段上sorting,不能相互抵消对方的工作。
施瓦茨变换
Schwartzian变换 ,也被称为装饰分类 – undecorate习语,使用固有的不稳定的sortingalgorithm进行稳定的sorting。
首先,使用包含主键(值)和辅助键(其索引或位置)的另一个数组来装饰每个数组元素:
array_walk($array, function(&$element, $index) { $element = array($element, $index); // decorate });
这将数组转换为:
[ ['Kale', 0], ['Kaleidoscope', 1], ['Aardvark', 2], ['Apple', 3], ['Leicester', 4], ['Lovely', 5] ]
现在,我们调整比较步骤; 我们再次比较第一个字母,但是如果它们是相同的,则使用辅助键来保留原始的sorting:
usort($array, function($a, $b) { // $a[0] and $b[0] contain the primary sort key // $a[1] and $b[1] contain the secondary sort key $tmp = strcmp($a[0][0], $b[0][0]); if ($tmp != 0) { return $tmp; // use primary key comparison results } return $a[1] - $b[1]; // use secondary key });
之后,我们展开:
array_walk($array, function(&$element) { $element = $element[0]; });
最终的结果是:
['Aardvark', 'Apple', 'Kale', 'Kaleidoscope', 'Leicester', 'Lovely']
什么是重用?
你必须重写你的比较函数来处理转换的数组元素; 你可能不想编辑你的微妙的比较函数,所以这里是一个比较函数的包装:
function stablecmp($fn) { return function($a, $b) use ($fn) { if (($tmp = call_user_func($fn, $a[0], $b[0])) != 0) { return $tmp; } else { return $a[1] - $b[1]; } }; }
让我们用这个函数来编写sorting步骤:
usort($array, stablecmp(function($a, $b) { return strcmp($a[0], $b[0]); }));
瞧! 您原始的比较代码回来了。
从PHP 5.3到闭包,也可以使用闭包来确定sorting顺序。
例如,假设$ array是一个包含月份属性的对象数组。
$orderArray = array("Jan","Feb","Mar","Apr","May","June","July","Aug","Sept","Oct","Nov","Dec"); usort($array, function($a, $b) use ($orderArray){ return array_search($a->month, $orderArray) - array_search($b->month, $orderArray); });
LINQ
在.NET中,LINQ经常用于sorting,比较函数提供了更好的语法,特别是当对象需要被多个字段sorting时。 LINQ to PHP有几个端口,包括YaLinqo library *。 有了它,数组可以用一行来sorting,而无需编写复杂的比较函数。
$sortedByName = from($objects)->orderBy('$v->name'); $sortedByCount = from($objects)->orderBy('$v->count'); $sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');
比较可以通过将callback作为第二个参数进一步定制,例如:
$sortedByFilenameNat = from($objects)->orderBy('$v->filename', 'strnatcmp');
这里'$v->count'
是function ($v) { return $v->count; }
的缩写function ($v) { return $v->count; }
function ($v) { return $v->count; }
(可以使用)。 这些方法链返回迭代器,如果需要的话,可以通过添加->toArray()
来将迭代器转换为数组。
在内部, orderBy
和相关方法调用适当的数组sorting函数( uasort
, krsort
, multisort
, usort
等)。
LINQ包含了许多受SQL启发的方法:过滤,分组,join,聚合等。它最适合于需要在不依赖数据库的情况下执行数组和对象的复杂转换的情况。
*由我开发,请参阅自述了解更多细节并与其他LINQ端口进行比较
从Nspl中对sorting函数进行sorting非常方便:
基本的sorting
// Sort array $sorted = sorted([3, 1, 2]); // Sort array in descending order $sortedDesc = sorted([3, 1, 2], true);
按function结果sorting
// Sort array by the result of a given function (order words by length) $sortedByLength = sorted(['bc', 'a', 'abc'], 'strlen'); $sortedByLengthDesc = sorted(['bc', 'a', 'abc'], true, 'strlen'); // Sort array by the result of user-defined function (order words by the 1st character) $sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], function($v) { return $v[0]; }); // Which is the same as $sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], itemGetter(0)); $sortedByTheFirstCharacterDesc = sorted(['bc', 'a', 'abc'], true, itemGetter(0)); // itemGetter(0) returns a function which takes an argument with access by index/key // and returns the value at index 0
sortingmultidimensional array
// Sort multidimensional array (sort list of users by their names) $users = [ array('name' => 'Robert', 'age' => 20), array('name' => 'Alex', 'age' => 30), array('name' => 'Jack', 'age' => 25), ]; $sortedByName = sorted($users, itemGetter('name')); $sortedByNameDesc = sorted($users, true, itemGetter('name')); // itemGetter('name') returns a function which takes an argument with access by index/key // and returns the value of the 'name' key
排列对象数组
// Lets assume we have class User(name, age) with properties name and age // and public methods getName() and getAge() $users = [ new User('Robert', 20), new User('Alex', 30), new User('Jack', 25), ]; // Sort list of objects by property value (sort list of users by their name) $sortedByName = sorted($users, propertyGetter('name')); $sortedByNameDesc = sorted($users, true, propertyGetter('name')); // propertyGetter('name') returns a function which takes an object // and returns the value of its 'name' property // Sort list of objects by method result (sort list of users by their age) $sortedByAge = sorted($users, methodCaller('getAge')); $sortedByAgeDesc = sorted($users, true, methodCaller('getAge')); // methodCaller('getAge') returns a function which takes an object // and returns the result of its getAge() method
用比较functionsorting
// Sort with a comparison function (order words lexicographically with strcmp) $sortedLexicographically = sorted(['bc', 'a', 'abc'], false, null, 'strcmp'); // Sort with user-defined comparison function (order words by the 1st character) $sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], false, null, function($v1, $v2) { return chr($v1[0]) - chr($v2[0]); });
你可以在这里看到所有这些例子。
最简单的方法是使用usort函数对数组进行sorting,而不进行循环:下面是一个例子:
$array_compare= array("0" =>4,"1"=>2,"2"=>500,"3"=>100);
这将按照取消顺序进行sorting:
usort($array_compare, function($a, $b) { return ($b['x1'] - $a['x1']) > 0 ? 1 :-1; });
这将按照顺序sorting:
usort($array_compare, function($a, $b) { return ($b['x1'] - $a['x1']) < 0 ? 1 :-1; });