[英]PHP - Sort multi-dimensional array by another array
I'm trying to sort a multi-dimensional array by another array, but have so far come up short.我正在尝试按另一个数组对多维数组进行排序,但到目前为止还不够。
array_multisort
seems be working only for real sorting. array_multisort
似乎只适用于真正的排序。
Suppose I have these 2 arrays:假设我有这两个数组:
$order = array(2,3,1);
$data = array(
array('id' => 1, 'title' => 'whatever'),
array('id' => 2, 'title' => 'whatever'),
array('id' => 3, 'title' => 'whatever')
);
Now I would like to sort my $data
array according to the order in my $order
array.现在我想根据
$order
数组中的顺序对$data
数组进行排序。
This is what I would like the result to be:这就是我想要的结果:
$data = array(
array('id' => 2, 'title' => 'whatever'),
array('id' => 3, 'title' => 'whatever')
array('id' => 1, 'title' => 'whatever'),
);
I can accomplish this easily by running a nested loop, but that would not scale well (my array is pretty big, and the arrays have many more fields).我可以通过运行嵌套循环轻松完成此操作,但这不能很好地扩展(我的数组非常大,并且数组有更多字段)。
In your example the ids in the $data array are are numbered consecutively and starting at 1. The code I give below assumes this is always the case.在您的示例中, $data 数组中的 id 是连续编号的,从 1 开始。我在下面给出的代码假定情况始终如此。 If this is not the case, the code does not work.
如果不是这种情况,代码将不起作用。
$result = array();
$index = 0;
foreach ($order as $position) {
$result[$index] = $data[$position - 1];
$index++;
}
At http://codepad.org/YC8w0yHh you can see that it works for your example data.在http://codepad.org/YC8w0yHh,您可以看到它适用于您的示例数据。
EDIT编辑
If the assumption mentioned above does not hold, the following code will achieve the same result:如果上述假设不成立,则以下代码将达到相同的结果:
<?php
$data = array(
array('id' => 1, 'title' => 'whatever'),
array('id' => 2, 'title' => 'whatever'),
array('id' => 3, 'title' => 'whatever')
);
$order = array(2,3,1);
$order = array_flip($order);
function cmp($a, $b)
{
global $order;
$posA = $order[$a['id']];
$posB = $order[$b['id']];
if ($posA == $posB) {
return 0;
}
return ($posA < $posB) ? -1 : 1;
}
usort($data, 'cmp');
var_dump($data);
See http://codepad.org/Q7EcTSfs for proof.请参阅http://codepad.org/Q7EcTSfs以获取证明。
By calling array_flip() on the $order array it can be used for position lookup.通过在 $order 数组上调用 array_flip(),它可以用于位置查找。 This is like a hashtable lookup, which is linear in time, or O(n).
这就像一个哈希表查找,它在时间上是线性的,或者说 O(n)。 You cannot do better.
你不能做得更好。
There is no built-in function for this in PHP and i am unable to think of any custom function, which would do this using usort. PHP 中没有内置函数,我无法想到任何自定义函数,它可以使用 usort 来做到这一点。 But array_map is simple enough, imo, so why not use it instead?
但是array_map已经足够简单了,imo,为什么不使用它呢?
$sorted = array_map(function($v) use ($data) {
return $data[$v - 1];
}, $order);
This would be how I would do.这就是我要做的。 I would use a custom usort function (arr_sort) in conjunction with the $data array.
我会结合 $data 数组使用自定义 usort 函数 (arr_sort)。
<?php
$order = array(2,3,1);
$data = array(
array('id' => 1, 'title' => 'whatever'),
array('id' => 2, 'title' => 'whatever'),
array('id' => 3, 'title' => 'whatever')
);
function arr_sort($a,$b){
global $order;
foreach ($order as $key => $value) {
if ($value==$a['id']) {
return 0;
break;
}
if ($value==$b['id']) {
return 1;
break;
}
}
}
usort($data,'arr_sort');
echo "<pre>";
print_r($data);
echo "<pre>";
For those of you who want to sort data based on an array with actual IDs, rather than based on an array with indexes like in the accepted answer - you can use the following simple comparison function for the usort
:对于那些想要根据具有实际 ID 的数组而不是根据已接受的答案中的索引数组对数据进行排序的人 - 您可以对
usort
使用以下简单的比较函数:
usort($data, function($a, $b) use ($order) {
$posA = array_search($a['id'], $order);
$posB = array_search($b['id'], $order);
return $posA - $posB;
});
So the following example will work fine and you won't get the Undefined offset
notices and an array with null
values:所以下面的例子可以正常工作,你不会得到
Undefined offset
通知和一个具有null
值的数组:
$order = [20, 30, 10];
$data = [
['id' => 10, 'title' => 'Title 1'],
['id' => 20, 'title' => 'Title 2'],
['id' => 30, 'title' => 'Title 3']
];
usort($data, function($a, $b) use ($order) {
$posA = array_search($a['id'], $order);
$posB = array_search($b['id'], $order);
return $posA - $posB;
});
echo '<pre>', var_dump($data), '</pre>';
Output:输出:
array(3) {
[0]=>
array(2) {
["id"]=>
int(20)
["title"]=>
string(7) "Title 2"
}
[1]=>
array(2) {
["id"]=>
int(30)
["title"]=>
string(7) "Title 3"
}
[2]=>
array(2) {
["id"]=>
int(10)
["title"]=>
string(7) "Title 1"
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.