php 按照类属性排序,在PHP中按对象属性排序数组?

问题是关于使用

usort的低效率,因为调用比较回调的开销。这个答案看看使用内置排序函数和非递归quicksort实现之间的区别。

答案随着PHP自2009年以来的演变而变化,所以我保持更新。旧的材料,虽然不再相关,但仍然有趣!

TL; DR:as of php 7.0.1,非递归快速排序不再比使用带有回调的usort快。这并不总是这样,这就是为什么下面的细节使有趣的阅读。真正的好处是,如果你基准你的问题,并尝试替代方法,你可以得出令人惊讶的结果。

2016年1月更新

在这里我们与php 7.0发布和7.1在途中!最后,对于这个数据集,内置usort是永远快一点 – 更快!

+-----------+------------+------------+------------+------------+------------+

| Operation | HHVM | php7.0.1 | php5.6.3 | 5.4.35 | 5.3.29 |

+-----------+------------+------------+------------+------------+------------+

| usort | *0.0445 | *0.0139 | 0.1503 | 0.1388 | 0.2390 |

| quicksort | 0.0467 | 0.0140 | *0.0912 | *0.1190 | *0.1854 |

| | 5% slower | 1% slower | 40% faster | 15% faster | 23% faster |

+-----------+------------+------------+------------+------------+------------+

2015年1月更新

当我最初在2009年回答这个问题时,我使用usort与非递归quicksort比较,看看是否有区别。事实证明,有显着差异,快速排序运行速度快3倍。

因为它现在是2015,我认为这可能是有用的重新访问这,所以我采取的代码排序15000对象使用usort和quicksort,并运行它在3v4l.org它运行在许多不同的PHP版本。全部结果如下:http://3v4l.org/WsEEQ

+-----------+------------+------------+------------+------------+------------+

| Operation | HHVM | php7alpha1 | php5.6.3 | 5.4.35 | 5.3.29 |

+-----------+------------+------------+------------+------------+------------+

| usort | *0.0678 | 0.0438 | 0.0934 | 0.1114 | 0.2330 |

| quicksort | 0.0827 | *0.0310 | *0.0709 | *0.0771 | *0.1412 |

| | 19% slower | 30% faster | 25% faster | 31% faster | 40% faster |

+-----------+------------+------------+------------+------------+------------+

原始笔记从2009年

我试了一个usort,并排序15000个人对象在大约1.8秒。

由于您担心调用比较函数的低效率,我将其与非递归Quicksort实现进行比较。这实际上是在大约三分之一的时间,大约0.5秒跑。

这里是我的代码,其基准的两种方法

// Non-recurive Quicksort for an array of Person objects

// adapted from http://www.algorithmist.com/index.php/Quicksort_non-recursive.php

function quickSort( &$array )

{

$cur = 1;

$stack[1]['l'] = 0;

$stack[1]['r'] = count($array)-1;

do

{

$l = $stack[$cur]['l'];

$r = $stack[$cur]['r'];

$cur--;

do

{

$i = $l;

$j = $r;

$tmp = $array[(int)( ($l+$r)/2 )];

// partion the array in two parts.

// left from $tmp are with smaller values,

// right from $tmp are with bigger ones

do

{

while( $array[$i]->age < $tmp->age )

$i++;

while( $tmp->age < $array[$j]->age )

$j--;

// swap elements from the two sides

if( $i <= $j)

{

$w = $array[$i];

$array[$i] = $array[$j];

$array[$j] = $w;

$i++;

$j--;

}

}while( $i <= $j );

if( $i < $r )

{

$cur++;

$stack[$cur]['l'] = $i;

$stack[$cur]['r'] = $r;

}

$r = $j;

}while( $l < $r );

}while( $cur != 0 );

}

// usort() comparison function for Person objects

function personSort( $a, $b ) {

return $a->age == $b->age ? 0 : ( $a->age > $b->age ) ? 1 : -1;

}

// simple person object

class Person {

var $age;

function __construct($age) {

$this->age = $age;

}

}

//---------test internal usort() on 15000 Person objects------

srand(1);

$people=array();

for ($x=0; $x<15000; $x++)

{

$people[]=new Person(rand(1,100));

}

$start=microtime(true);

usort( $people, 'personSort' );

$total=microtime(true)-$start;

echo "usort took $total\n";

//---------test custom quicksort on 15000 Person objects------

srand(1);

$people=array();

for ($x=0; $x<15000; $x++)

{

$people[]=new Person(rand(1,100));

}

$start=microtime(true);

quickSort( $people );

$total=microtime(true)-$start;

echo "quickSort took $total\n";

一个有趣的建议是添加一个__toString方法到类和使用sort(),所以我试过了。麻烦的是,你必须传递SORT_STRING作为第二个参数来排序,让它实际上调用魔术方法,这有副作用,而不是数字排序。为了解决这个问题,你需要用零填充数字,使它正确排序。净结果是,这比usort和自定义quickSort慢

sort 10000 items took 1.76266698837

usort 10000 items took 1.08757710457

quickSort 10000 items took 0.320873022079

这里是使用__toString()的sort()的代码:

$size=10000;

class Person {

var $age;

function __construct($age) {

$this->age = $age;

$this->sortable=sprintf("%03d", $age);

}

public function __toString()

{

return $this->sortable;

}

}

srand(1);

$people=array();

for ($x=0; $x

{

$people[]=new Person(rand(1,100));

}

$start=microtime(true);

sort( $people, SORT_STRING);

$total=microtime(true)-$start;

echo "sort($size) took $total\n"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值