这里有很多问题,询问如何在PHP中对多维数组进行排序.答案是usort().我知道.但是我有一个问题需要更进一步,我在这里看不到类似的答案.
我有一系列记录,每个记录都包含一个国家ID(如果您愿意,可以是国家/地区名称;它不相关).
我的任务是以有利于某些国家的方式对阵列进行排序.这是动态的 - 即支持的国家的选择取决于用户的配置.我有一个单独的数组,它指定了前几个国家所需的排序顺序; 来自其他国家的结果只会在列表末尾未分类.
所以问题是:如何在usort()不使用全局变量的情况下获得此排序标准.并且最好不要将条件数组注入到主数组的每个元素中('如果我还要循环它,那么,使用它的重点是什么usort()?)
请注意:由于它与这里的答案相关,我暂时停留在PHP 5.2上,所以我不能使用匿名函数.我们正在升级,但是现在我需要能够解决5.2的问题.(5.3/5.4的答案也会受到欢迎,特别是如果它们使它变得更容易,但我将无法使用它们)
我使用usort和用户比较函数来对对象数组进行排序.在对这些对象的数组运行usort之后,我发现对象的某些值随着它们在数组中的位置而发生了变化.我错过了什么?我不相信我的用户比较功能有任何副作用.我们是如何解构/重建对象的?
这是我正在使用的用户比较功能:
private function SortArrayOfSegments($segments){
foreach($segments as $segment){
echo '<pre>';
var_dump($segment);
}
usort($segments, "AirObject::CompareSegments");
foreach($segments as $segment){
var_dump($segment);
echo '</pre>';
}
return $segments;
}
public static function CompareSegments($a, $b){
$interval = date_diff(date_create($a->StartDateTime->GetString()),
date_create($b->StartDateTime->GetString()));
if($interval->invert == 1){
return 1;
}else if($interval->y == 0 && $interval->m == 0 && $interval->d == 0
&& $interval->i == 0 && $interval->s == 0 && $interval->h == 0){
return 0;
}else if($interval->invert == 0){
return -1;
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用的对象如下所示:
object(AirSegment)#14 (12) {
["StartDateTime"]=>
object(VDateTime)#27 (4) { …Run Code Online (Sandbox Code Playgroud) 我有一个数组排序功能如下:
public function sortAscending($accounts)
{
function ascending($accountA, $accountB) {
if ($accountA['AmountUntilNextTarget'] == $accountB['AmountUntilNextTarget']) {
return 0;
}
return ($accountA['AmountUntilNextTarget'] < $accountB['AmountUntilNextTarget']) ? -1 : 1;
}
usort($accounts, $ascending);
return $accounts;
}
Run Code Online (Sandbox Code Playgroud)
显然,这并不理想,因为搜索密钥很难编码.我以为我会通过将键作为参数传递给外部函数来使这个泛型,但是这在内部函数中是超出范围的.我试图通过使用一个闭包来解决这个问题,它可以访问param,而不是内部函数,如下所示:
public function sortAscending($accounts, $key)
{
$ascending = function($accountA, $accountB) {
if ($accountsA[$key] == $accountB[$key]) {
return 0;
}
return ($accountA[$key] < $accountB[$key]) ? -1 : 1;
}
usort($accounts, $ascending);
return $accounts;
}
Run Code Online (Sandbox Code Playgroud)
但是usort()只接受函数名,所以这不起作用.任何人都可以看到(更好?)实现这一目标的方式?
以下代码位于一个本身位于类中的函数中.其目的是避免每个$ filter值有一个排序函数:
$GLOBAL['filter'] = $filter;
usort($this->data, function($arr1, $arr2) {
return ($arr1[$GLOBALS['filter']] > $arr2[$GLOBALS['filter']]) ? 1 : -1;
});
Run Code Online (Sandbox Code Playgroud)
我的解决方案完美无缺,但我发现它相当不优雅.有人有想法在不诉诸$ GLOBALS变量的情况下实现同一目标吗?
谢谢你的主张
起初,我给的链接代码:http://ideone.com/6k8R6
在我的英特尔Core 2 Duo,PHP 5.4.6的结果是:
usort: 7.8763520717621
quicksort: 2.9220938682556
(usort慢于quicksort)
但在Ideone结果是:
usort: 0.0313699245453
quicksort: 0.0621209144592
(usort比快quicksort)
我还检查代码在我朋友的电脑(英特尔酷睿i5,PHP 5.4.4),并且usort也更快.
我的问题是:为什么有时quicksort比usort更快,有时候usort更快?
我要做的是对包含十进制值的多维数组进行排序.根据我的测试,浮标很难正确订购.
Array
(
[0] => Array
(
[company] => Ebay
[weight] => 4.6
)
[1] => Array
(
[company] => Ebay
[weight] => 1.7
)
[2] => Array
(
[company] => Ebay
[weight] => 3.7
)
)
usort($array, 'order_by_weight');
// Sorts DESC highest first
function order_by_weight($a, $b) {
return $b['weight'] - $a['weight'];
}
Run Code Online (Sandbox Code Playgroud)
降序排序这些数字的最佳方法是什么?
是否有更紧凑的方法来使用 PHP \xe2\x89\xa5 7.0按两个参数/字段对数组进行排序(使用spaceship 运算符) <=>?
现在我要排序的技巧是首先按第二个参数,然后按第一个参数:
\n// Sort by second parameter title\nusort($products, function ($a, $b) {\n return $a[\'title\'] <=> $b[\'title\']; // string\n});\n\n// Sort by first parameter brand_order\nusort($products, function ($a, $b) {\n return $a[\'brand_order\'] <=> $b[\'brand_order\']; // numeric\n});\nRun Code Online (Sandbox Code Playgroud)\n这给了我我想要的结果;产品首先按品牌排序,然后按名称排序。
\n我只是想知道是否有办法做到这一点usort。
这是我的问题作为代码片段。这个例子可以在这里测试。
\n<pre><?php\n \n<!-- Example array -->\n$products = array();\n\n$products[] = array("title" => "Title A", \n "brand_name" => "Brand B",\n "brand_order" => 1);\n$products[] = …Run Code Online (Sandbox Code Playgroud)我想我可能已经阅读usort过StackOverflow上的每篇文章,但我无法解决这个问题.这可能usort不是我需要的工具吗?这里有一些我正在使用的数组(我将其分配给$allPages):
Array
(
[0] => Page Object
(
[id] => 4
[slug] => articles
[created_on] => 2009-08-06 07:16:00
)
[1] => Page Object
(
[id] => 99
[slug] => a-brief-history
[created_on] => 2011-04-25 12:07:26
)
[2] => Page Object
(
[id] => 98
[slug] => we-arrive
[created_on] => 2011-04-24 13:52:35
)
[3] => Page Object
(
[id] => 83
[slug] => new-year
[created_on] => 2011-01-02 14:05:12
)
)
Run Code Online (Sandbox Code Playgroud)
我最终试图对created_on价值进行分类,但就目前而言,我决定能够对它们中的任何一个进行排序!当我尝试普通cmp($a, $b)类型回调时 …
在PHP中,usort函数有两个参数:array to sort和callback.回调也有两个参数:$ a和$ b.然后,我们以任何我们想要的方式比较这两者.它总是让我吃惊,因为这个用例usort是不是太普通了.我们通常使用相同的属性对值进行排序,或者对$ a和$ b使用相同的逻辑.例如,如果我们想按长度排序:
$animals = ['dog', 'tiger', 'giraffe', 'bear'];
usort($animals, function ($a, $b) {
return strlen($a) - strlen($b);
});
Run Code Online (Sandbox Code Playgroud)
这会奏效,但我们需要说strlen两遍.这样说会更好:
usort($animals, function ($element) {
return strlen($element);
});
Run Code Online (Sandbox Code Playgroud)
或者甚至像这样:
usort($animals, 'strlen');
Run Code Online (Sandbox Code Playgroud)
我自己编写了这种函数(使用PHP 7的好东西,但它可以很容易地改为PHP 5):
function simple_usort(array &$array, callable $callback): bool
{
return usort($array, function ($a, $b) use ($callback) {
return $callback($a) <=> $callback($b);
});
}
Run Code Online (Sandbox Code Playgroud)
它工作得很好,但是它不是已经在其他功能中用PHP构建了吗?如果没有,为什么PHP不支持这种非常流行和方便的排序方式?
为什么小数没有正确排序:
13
11
14
10
12.5
---------------------------------------------------------
descending order:
14
12.5
13
11
10
Run Code Online (Sandbox Code Playgroud)
使用此代码:
class Customer {
public $score;
public function __construct($score) {
$this->score = $score;
}
}
$customers = [];
$customers[] = new Customer(13);
$customers[] = new Customer(11);
$customers[] = new Customer(14);
$customers[] = new Customer(10);
$customers[] = new Customer(12.5);
if(is_array($customers) && count($customers) > 0)
{
foreach($customers as $customer)
{
echo '<div>'.$customer->score.'</div>';
}
}
echo '<hr/>';
echo '<div>descending order:</div>';
usort($customers, function($a, $b) {
return $b->score - $a->score;
}); …Run Code Online (Sandbox Code Playgroud)