PHP 二维数组排序

昨天整理了 PHP 一般数组排序的常用方法,但都是针对一维数组的排序。其实在应用中对二维数组排序的需求也是挺多的,常见的情况是,一个二维数组,需要对其中的某一维或者多维进行排序。现在我就接着昨天的主题,更进一步的总结一下 PHP 对二维数组排序一般有那些方法。

PHP 也有对二维数组进行排序的方法,昨天的文章 PHP 数组排序 中就有提到过,它们是 array_multisort() 和那几个用户定义函数。也就是说,这些函数既可以对一维数组进行排序,也可以对二维数组进行排序,是不是很厉害呢 ^_^ 昨天只是介绍了它们对一维函数排序的用法,今天就说说它们对于二维数组的排序是怎么用的。

当然,对于二维数组的排序方法,我们也可以不局限与 PHP 的内置函数,我们可以定义自己的二维数组排序函数,本文也将会尝试给出一个这样子的解决方案供参考。

用 array_multisort() 对二维数组排序

上一篇文章 PHP 数组排序 已经了解过 array_multisort() 排序的要点,那就是“输入数组被当成一个表的列并以行来排序”。这个放到二维数组的排序中又应该怎样来理解呢?可以这样理解,表的最后一列是二维数组的元素。操作也很简单,只需要将二维数组的需要排序的维度的数据抽出来组成一维数组,然后将这些一维数组作为参数传给函数 array_multisort(),并且将该二维数组作为最后一个参数传入即可。

多说无益,直接上代码:

// 初始化二位数组
$arr	= array();
$num	= 10;
for($i = 0; $i < $num; $i ++){
	$a	= array();
	$a['k1']	= rand(1,100);
	$a['k2']	= rand(1,100);
	$a['k3']	= rand(1,100);
	$a['k4']	= rand(1,100);

	$arr['k'.$i]	= $a;
}

echo "排序前数据\n";
show_arr($arr);

/*******************排序开始*************************/
// 取出需要排序的维度
$k1	= array();
$k2	= array();
foreach($arr as $val){
	$k1[]	= $val['k1'];
	$k2[]	= $val['k2'];
}

// 排序
array_multisort($k1,$k2,$arr);
unset($k1);
unset($k2);
/*******************排序结束*************************/

echo "排序后数据\n";
show_arr($arr);

function show_arr($arr){
	foreach($arr as $key => $val){
		echo "\t".$key.":";
		echo "\t".$val['k1'];
		echo "\t".$val['k2'];
		echo "\t".$val['k3'];
		echo "\t".$val['k4'];

		echo "\n";
	}
}

运行结果如下:

运行结果
运行结果

代码中先将二维数组中的键值为 k1 和 k2 的值抽取出来作为一维数组,然后将这两个一维数组作为排序的依据传给函数,最后将二维数组作为最后一个参数传给函数。这就是使用函数 array_multisort() 对二维数组进行排序的全部了。从结果中可以看出,二维数组确实是按照 k1 和 k2 维度的数值进行排序了。维度 k1 的数值是升序的,当 k1 中的值相等时,则按维度 k2 的值来排序。

这里将二维数组的键打印出来是想说明一点,arrar_multisort() 对数组进行排序时,数组的键-值对是保持对应关系的(键为数字时例外)。

使用 usort() 对二维数组进行排序

那几个用户定义的 PHP 内置函数都可以对二维数组进行排序的,这里就只是挑 usort() 来进行说明即可。这种排序函数的针对性比较强,可能每次使用都需要重新定义一个比较函数,但功能也比较强大,可以对一些不常见的数据进行排序。

还是举栗子说明吧。


// 初始化二位数组
$arr	= array();
$num	= 10;
for($i = 0; $i < $num; $i ++){
	$a	= array();
	$a['k1']	= rand(1,100);
	$a['k2']	= rand(1,100);
	$a['k3']	= rand(1,100);
	$a['k4']	= rand(1,100);

	$arr['k'.$i]	= $a;
}

echo "排序前数据\n";
show_arr($arr);

/*******************排序开始*************************/
usort($arr,'user_cmp');

//定义比较函数
function user_cmp($v1,$v2){
	$a	= $v1['k1'];
	$b	= $v2['k1'];

	if($a == $b)
		return 0;
	return ($a > $b) ? 1 : -1;
}
/*******************排序结束*************************/

echo "排序后数据\n";
show_arr($arr);

function show_arr($arr){
	foreach($arr as $key => $val){
		echo "\t".$key.":";
		echo "\t".$val['k1'];
		echo "\t".$val['k2'];
		echo "\t".$val['k3'];
		echo "\t".$val['k4'];

		echo "\n";
	}
}

运行结果如下:

Screenshot from 2016-08-07 13:59:20

结果已经很明显了,维度 k1 已经是升序了。但是要注意一点,用此函数排序会丢失键-值的对应关系,如果需要保留键-值对应的话,可以使用 uasort() 函数。

自定义的二维数组排序函数

自定义的函数就更加灵活了,直接上代码 ^_^


// 初始化二位数组
$arr	= array();
$num	= 10;
for($i = 0; $i < $num; $i ++){
	$a	= array();
	$a['k1']	= rand(1,100);
	$a['k2']	= rand(1,100);
	$a['k3']	= rand(1,100);
	$a['k4']	= rand(1,100);

	$arr['k'.$i]	= $a;
}

echo "排序前数据\n";
show_arr($arr);

/*******************排序开始*************************/
$arr	= user_sort($arr,'k1');

// 自定义二维数组排序函数
function user_sort($arr,$key,$type='asc'){
	$keys =  array();
	$new = array();

	foreach ($arr as $k=>$v){
		$keys[$k] = $v[$key];
	}

	if($type == 'asc'){
		asort($keys);
	}else{
		arsort($keys);
	}

	reset($keys);
	// 根据新顺序重组二维数组
	foreach ($keys as $k=>$v){
		$new[$k] = $arr[$k];
	}
	return $new; 
}
/*******************排序结束*************************/

echo "排序后数据\n";
show_arr($arr);

function show_arr($arr){
	foreach($arr as $key => $val){
		echo "\t".$key.":";
		echo "\t".$val['k1'];
		echo "\t".$val['k2'];
		echo "\t".$val['k3'];
		echo "\t".$val['k4'];

		echo "\n";
	}
}

运行结果如下:

运行结果
运行结果

这就是自定义的二维数组排序函数,它可以按照二维数组的某一维来排序,还可以指定是顺序还是倒序来排序。

最后

以上,是我要介绍的三种二维数组的排序方法。

array_multisort() 是 PHP 内置的数组排序函数,功能强大,适应范围广。为了使本篇文章更加容易理解,我故意省去了该函数的一些排序属性,其实它还可以指定是升序还是降序,是将元素作为数值排序还是作为字符串来排序等等。如果能够很好的掌握此函数的使用方法,那么大部分的数组排序问题都可以很好的解决了。

PHP 内置的用户定义比较规则的排序函数也能解决二维数组的排序问题,它最大的优点就是用户可以自己制定比较规则了。

对于用户完全自定义的二维数组排序函数,个人认为,如果不是逼不得已,尽量不用自己定义,因为 PHP 内置的已经可以解决几乎所有的排序问题了,而且自己写的性能也是不大自信的 ^_^

THE END

本文作者: chenishr

本文标题:《PHP 二维数组排序》

本文地址: http://blog.chenishr.com/?p=539

©版权所有,除非注明, 永在路上文章均为原创,转载请以链接形式注明出处和作者细信息。

发表评论

电子邮件地址不会被公开。 必填项已用*标注