+
 新版

关于PHP 的数组排序函数的困惑

php_ 发布于 2020/03/03 20:05
阅读 858
收藏 1
PHP
$age=array("Elon"=>"47","Bill"=>"56","A"=>"56");
arsort($age); // 结果:$age == ["A"=>"56", "Bill"=>"56", "Elon"=>"47"] <=== 注意看这行代码
asort($age); //  结果:$age == ["Elon"=>"47", "A"=>"56", "Bill"=>"56"]
arsort($age); // 结果:$age == ["Bill"=>"56", "A"=>"56", "Elon"=>"47"] <=== 以及这行代码

代码如上。为什么第一次调用 arsort() 与 第二次调用 arsort() 的结果是不一样的呢?

我想要对数组进行降序排序,遇上【键值】大小相同时,各【键名】的位置与其在数组中出现的先后顺序保持一致,这个要自己写排序算法才能实现吗?

加载中
1
千一
千一

你第二次调用的是 asort 不是 arsort

第二个字母 r 少了。。。。

php_
php_
不是,我是特意调用的。一个降序一个增序。
0
tcxu
tcxu

为了保证"遇上【键值】(即元素值)大小相同时,各【键名】的位置与其在数组中出现的先后顺序保持一致" ,编写了如下对关联数组实施"泡沫排序"的方法的代码。结果似乎达到了楼主的诉求。有关途径叙述如下。

  1. 依据 关联数组 $arr 的数据, 建立 MyClass 对象数组 $a;
  2. 按类 MyClass 的属性 age 对实体/对象数组 $a 实行冒泡降序排序;
  3. 将经过排序处理的实体/对象数组 $a 的数据,依次添加到最终保存结果的关联数组 $a_sorted 之中。
  4. 输出经过元素值递减排序处理的关联数组 $a_sorted。
<?php
class MyClass{ //类定义
	public $name;
	public $age;
	function __construct($name='',$age=''){ //构造方法
		$this->name=$name;
		$this->age=$age;
		}
	}
$arr=array("Lily"=>"31","Wang"=>"41","Coco"=>"39","Yu"=>"40","John"=>"41","Don"=>"41");
echo '输出原始数组:';
foreach ($arr as $key => $value )  
	echo $key.'=>'.$value.', ';

$i=0; //依据 关联数组 $arr 的数据, 建立 MyClass 对象数组 $a
foreach ($arr as $key => $value ) {
  $a[$i]=new MyClass($key, $value);
  $i++;
}

//按属性 MyClass 的属性 age 对实体数组 $a 实行冒泡降序排序
$len=count($a);
for($i=1;$i<$len;$i++)
	for($j=0;$j<$len-$i;$j++)
		if(strcmp($a[$j]->age, $a[$j+1]->age) <0){
			$tmp = $a[$j+1];
			$a[$j+1] = $a[$j];
			$a[$j] = $tmp;			
		}
//根据实体数组 $a 的数据,依次添加到最终的关联数组之中。
$a_sorted=array();
$i=0;
foreach ($a as $key => $value ) 
$a_sorted = $a_sorted + array($a[$i]->name => $a[$i++]->age);

echo '<br> 输出排序后的数组: '; 
foreach ($a_sorted as $key => $value )  
	echo $key.'=>'.$value.', ';
?>
输出原始数组:Lily=>31, Wang=>41, Coco=>39, Yu=>40, John=>41, Don=>41, 
输出排序后的数组: Wang=>41, John=>41, Don=>41, Yu=>40, Coco=>39, Lily=>31,

 

0
tcxu
tcxu

将2维数组排序后得 $arrAges3。但是你忘了必须再将 二维数组  $arrAges3 转变回来, 变成关联数组  $arrAges4。最后,再输出这个 关联数组  $arrAges4。
修改:
echo "排序后:<br />";  之后的所有代码行, 换成以下代码:

$arrAges4=array();
for ($i=0;$i<count($arrAges3);$i++) // 二维数组 变 关联数组
$arrAges4 = $arrAges4 + array($arrAges3[$i][0] => $arrAges3[$i][1]);
echo '排序后的关联数组<br>';
foreach($arrAges4 as $key => $value) 
echo $key.' => '.$value. '<br> ';

注意,在冒泡排序的比较之中,只能用 '<', 而万万不能用 '<='。 这样就保证了键值相等时,不会调换位置,进而保证了 "遇上【键值】大小相同时,各【键名】的位置与其在数组中出现的先后顺序保持一致"。

此外,在冒泡排序的循环之中,应当加上一个布尔变量 $foo,用来监视每次内循环是否有交换发生。若没有交换,说明数组的各个元素已经按降/升序排列完毕,不必再继续"扫描"了。因此就可以立马跳出外循环,结束排序任务。比如用原本就已经排序好的数组作参数,若没有加这个 布尔变量 $foo, 那就要按规定做数次循环、进行比较,这些都是"无用功"。如果有了这个  布尔变量 $foo,那在 第一轮扫描过后,就会发现 $foo 仍然是 FALSE,于是就可以立马停止循环,完成排序。如此这般,免去了后来的不必要的循环操作。特将你的冒泡排序法修改如下, 供参考。  

function bubbleSort($array){
    $length = count($array);
    if (!$length) {
        return $array;
    }
    for ($outer = 0; $outer < ($length - 1); $outer++) {
		$foo = FALSE;
        for ($inner = 0; $inner < ($length - $outer - 1); $inner++) {
            if ($array[$inner][1] < $array[($inner+1)][1]) {
                $tmp = $array[$inner];
                $array[$inner] = $array[($inner+1)];
                $array[($inner+1)] = $tmp;
				$foo = TRUE;
            }
        }
		if ($foo == FALSE) break;
    }
    return $array;
}

 

php_
php_
呃,二维数组又转回关联数组……,很细心嘛,这很切合题意。不过我需要的主要还是还是最后的输出结果,不做这个转换可以提高下运行效率:grin: 像我这种菜鸟,对变量 $foo ,理解起来还是比较吃力的,不明觉厉。
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部