根据另一个关联数组的键顺序按其键对平面关联数组进行排序

问题描述 投票:0回答:5

我有两个数组。

一个是较大的数据位:

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
)
php arrays sorting ksort custom-sort
5个回答
5
投票

简单的 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)
}

2
投票

这是一个使用 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.


2
投票

使用

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);

一开始很好很干净,但最终却变得相当丑陋和不清楚。我现在倾向于其他一些答案而不是我的答案。


1
投票
$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)
}

有关数组的 +,请参阅

数组运算符


0
投票

因为您的

$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);
© www.soinside.com 2019 - 2024. All rights reserved.