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

发布于 2024-11-17 08:02:27 字数 590 浏览 3 评论 0原文

我有两个数组。

一个是较大的数据位:

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
)

I have two arrays.

One is a larger bit of data:

Array
(
    [12] => blah
    [36] => foo
    [58] => blah
    [60] => blah
    [72] => blah
    [90] => bar
)

The other is a smaller subset of different but related data in a different order, with each key corresponding to the same key in the larger array:

Array
(
    [36] => foo data
    [90] => bar data
    [12] => blah data
)

Now, my question is, how do I get the first array to be in such an order so that the keys in the first array that have corresponding keys in the second array will appear first and in the same order as the second array?

Thus, like this:

Array
(
    [36] => foo
    [90] => bar
    [12] => blah
    [58] => blah
    [60] => blah
    [72] => blah
)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我三岁 2024-11-24 08:02:27

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

Simple O(n) solution.

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

Output:

array(5) {
  [36]=>
  int(2)
  [60]=>
  int(4)
  [12]=>
  int(1)
  [58]=>
  int(3)
  [72]=>
  int(5)
}
汹涌人海 2024-11-24 08:02:27

这是一个使用带有闭包的 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),你可以使用全局来做类似的事情,但它根本不干净。

Here's an example using uksort with closure, it should be more effective on big array i think, but i haven't done any benchmark so... difficult to really confirm w/o test.

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

result:

Array
(
    [36] => foo
    [90] => bar
    [12] => blah
    [72] => blah
    [58] => blah
    [60] => blah
)

If you can't use closure (php <5.3) you can do something similar using a global but it's not clean at all.

鯉魚旗 2024-11-24 08:02:27

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

开始时干净整洁,但最终却变得丑陋且不清楚。我现在倾向于其他一些答案而不是我的答案。

use uksort

edit: fixed syntax/logic errors pointed out by malko. thank you.

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

This started off nice and clean, but ended up pretty ugly and unclear. I now I'm leaning toward some of the other answers rather than mine.

↙厌世 2024-11-24 08:02:27
$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)
}

请参阅数组运算符了解数组的+

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

Output:

array(5) {
  [36]=>
  int(2)
  [60]=>
  int(4)
  [12]=>
  int(1)
  [58]=>
  int(3)
  [72]=>
  int(5)
}

See Array Operators for the + for arrays.

金兰素衣 2024-11-24 08:02:27

由于 $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);

我的上述脚本都不能保证异常值按升序排序。如果需要,请添加辅助排序规则。 (演示

$priority = array_flip(array_keys($sorted_array));
uksort(
    $array_to_sort,
    fn($a, $b) => [($priority[$a] ?? PHP_INT_MAX), $a] <=> [($priority[$b] ?? PHP_INT_MAX), $b]
);
var_export($array_to_sort);

Because all keys of your $sorted_array data are found in the $array_to_sort, you don't need a sorting algorithm. Just replace the entire payload of $sorted_array with the entire payload of $array_to_sort. PHP will honor the first array's key order while replacin values, then will append the other unmentioned associative elements.

Code: (Demo)

var_export(
    array_replace($sorted_array, $array_to_sort)
);

Yes, it is just that simple.


If your sorting array may have keys that are not found in the array to be sorted, then leveraging a lookup array with uksort() is sensible. (Demo)

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

Neither of my above scripts guarantee that the outliers are sorted ascending. If this is needed, add a secondary sorting rule. (Demo)

$priority = array_flip(array_keys($sorted_array));
uksort(
    $array_to_sort,
    fn($a, $b) => [($priority[$a] ?? PHP_INT_MAX), $a] <=> [($priority[$b] ?? PHP_INT_MAX), $b]
);
var_export($array_to_sort);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文