我有两个数组。
一个是较大的数据位:
Array
(
[12] => blah
[36] => foo
[58] => blah
[60] => blah
[72] => blah
[90] => bar
)
另一个是不同顺序的不同但相关数据的较小子集,每个键对应于较大数组中的相同键:
Array
(
[36] => foo data
[90] => bar data
[12] => blah data
)
现在,我的问题是,如何让第一个数组按这样的顺序排列,以便第一个数组中与第二个数组中具有对应键的键首先出现,并且顺序与第二个数组相同?
因此,像这样:
Array
(
[36] => foo
[90] => bar
[12] => blah
[58] => blah
[60] => blah
[72] => blah
)
简单的 O(n) 解决方案。
$arr1 = array(12 => 1, 36 => 2, 58 => 3, 60 => 4, 72 => 5);
$arr2 = array(36 => 1, 60 => 2, 12 => 1);
$result = array();
foreach($arr2 as $key => $value) {
$result[$key] = $arr1[$key];
unset($arr1[$key]);
}
foreach($arr1 as $key => $value) {
$result[$key] = $arr1[$key];
}
var_dump($result);
输出:
array(5) {
[36]=>
int(2)
[60]=>
int(4)
[12]=>
int(1)
[58]=>
int(3)
[72]=>
int(5)
}
这是一个使用 uksort 闭包的示例,我认为它在大数组上应该更有效,但我还没有做过任何基准测试,所以......很难真正确认没有测试。
$a = array(
12 => 'blah'
,36 => 'foo'
,58 => 'blah'
,60 => 'blah'
,72 => 'blah'
,90 => 'bar'
);
$b = array(
36 => 'foo data'
,90 => 'bar data'
,12 => 'blah data'
);
$keysPosition = array_flip(array_keys($b));
uksort($a,function($a,$b) use ($keysPosition){
if(isset($keysPosition[$a],$keysPosition[$b])){
return $keysPosition[$a]>$keysPosition[$b]?1:-1;
}else if( isset($keysPosition[$a]) ){
return -1;
}else if( isset($keysPosition[$b]) ){
return 1;
}
return 0;
});
print_r($a);
结果:
Array
(
[36] => foo
[90] => bar
[12] => blah
[72] => blah
[58] => blah
[60] => blah
)
如果你不能使用闭包(php <5.3) you can do something similar using a global but it's not clean at all.
uksort
编辑:修复了 malko 指出的语法/逻辑错误。谢谢你。
$array_to_sort = array
(
12 => "blah",
36 => "foo",
58 => "blah",
60 => "blah",
72 => "blah",
90 => "bar"
);
$sorted_array = array(
36 => "foo data",
90 => "bar data",
12 => "blah data"
);
global $sorted_array_keys;
$sorted_array_keys = array_keys($sorted_array);
function cmp($a, $b)
{
global $sorted_array_keys;
$a_in_array = in_array($a, $sorted_array_keys);
$b_in_array = in_array($b, $sorted_array_keys);
if ($a_in_array && $b_in_array) {
return array_search($a, $sorted_array_keys) - array_search($b, $sorted_array_keys);
} else if ( $a_in_array ) {
return -1;
} else {
return 1;
}
}
uksort ( $array_to_sort , cmp );
print_r($array_to_sort);
一开始很好很干净,但最终却变得相当丑陋和不清楚。我现在倾向于其他一些答案而不是我的答案。
$array1 = array(12 => 1, 36 => 2, 58 => 3, 60 => 4, 72 => 5);
$array2 = array(36 => 1, 60 => 2, 12 => 1);
# obtaining keys in the order of question
$result = array_intersect_key($array2, $array1);
# assign values from original $array1
foreach($result as $key => &$value) {
$value = $array1[$key];
}
unset($value); # kill reference for safety
# add missing elements from $array1
$result += $array1;
var_dump($result);
输出:
array(5) {
[36]=>
int(2)
[60]=>
int(4)
[12]=>
int(1)
[58]=>
int(3)
[72]=>
int(5)
}
有关数组的 +
,请参阅
数组运算符。
因为您的
$sorted_array
数据的所有键都可以在 $array_to_sort
中找到,所以您不需要排序算法。只需将 $sorted_array
的整个有效负载替换为 $array_to_sort
的整个有效负载即可。 PHP 在替换值时将遵循第一个数组的键顺序,然后附加其他未提及的关联元素。
代码:(演示)
var_export(
array_replace($sorted_array, $array_to_sort)
);
是的,就是这么简单。
如果您的排序数组可能具有在要排序的数组中找不到的键,那么利用带有
uksort()
的查找数组是明智的。 (演示)
$priority = array_flip(array_keys($sorted_array));
uksort(
$array_to_sort,
fn($a, $b) => ($priority[$a] ?? PHP_INT_MAX) <=> ($priority[$b] ?? PHP_INT_MAX)
);
var_export($array_to_sort);