记一次数组操作:数组 A 根据数组 B 排序

记一次数组操作:数组A根据数组B排序


前言

最近遇到一个比较坑的事,应该也算是我自己平时观察不仔细的锅:在SQL中,如果使用in的字段是主键,且为数字。查询的结果会自动根据主键升序排序。

SELECT * FROM city WHERE ID IN (2,7,10,1,30,9,53)

file
而这并不是我想要的数据顺序,所以只能去重新调整顺序。

解决

首先将问题简化一下:假设我们现有一个一维数组$arr1,一个多维数组$arr2,现在需要$arr2的ID根据$arr1排序。

$arr1 = [2,7,10,1,30,9,53];
$arr2 = [
    ["ID" => 1, "Name" => "Kabul"],
    ["ID" => 2, "Name" => "Qandahar"],
    ["ID" => 7, "Name" => "Haag"],
    ["ID" => 9, "Name" => "Eindhoven"],
    ["ID" => 10, "Name" => "Tilburg"],
    ["ID" => 30, "Name" => "Delft"],
    ["ID" => 53, "Name" => "Tafuna"],
];

在解決问题之前我们先回顾一下array_flip()array_replace()

1. array_flip()

array_flip($array) 反转/交换数组(一维数组)中的键名和对应关联的键值。

<?php
    $a1=array("a"=>"red","b"=>"green","c"=>"blue","d"=>"yellow");
    $result=array_flip($a1);
    print_r($result);

    //result:
    Array
    (
        [red] => a
        [green] => b
        [blue] => c
        [yellow] => d
    )

?>

2. array_replace()

array_replace(array1,array2,array3...)用后面数组的值替换第一个数组的值。

如果一个键存在于第一个数组 array1 同时也存在于第二个数组 array2,第一个数组 array1 中的值将被第二个数组 array2 中的值替换。如果一个键仅存在于第一个数组 array1,它将保持不变。

如果一个键存在于第二个数组 array2,但是不存在于第一个数组 array1,则会在第一个数组array1 中创建这个元素。

如果传递了多个替换数组,它们将被按顺序依次处理,后面数组的值将覆盖之前数组的值。

<?php
    //示例1
    $a1=array("a"=>"red","b"=>"green");
    $a2=array("a"=>"orange","burgundy");
    print_r(array_replace($a1,$a2));

    //result
    Array ( [a] => orange [b] => green [0] => burgundy)

    //示例2
    $a3=array("a"=>"red","green");
    $a4=array("a"=>"orange","b"=>"burgundy");
    print_r(array_replace($a3,$a4));

    //result
    Array ( [a] => orange [0] => green [b] => burgundy)

    //示例3
    $a5=array("red","green");
    $a6=array("blue","yellow");
    $a7=array("orange","burgundy");
    print_r(array_replace($a5,$a6,$a7));

    //result 
    Array ( [0] => orange [1] => burgundy)
?>

实现

根据上面两个函数,可以先将$arr1键值交换,然后将$arr2里的ID的值作为$arr3第一维的键,最后用$arr3替换$arr1,就可以实现排序了。

$arr1 = [2, 7, 10, 1, 30, 9, 53];
$arr2 = [
    ["ID" => 1, "Name" => "Kabul"],
    ["ID" => 2, "Name" => "Qandahar"],
    ["ID" => 7, "Name" => "Haag"],
    ["ID" => 9, "Name" => "Eindhoven"],
    ["ID" => 10, "Name" => "Tilburg"],
    ["ID" => 30, "Name" => "Delft"],
    ["ID" => 53, "Name" => "Tafuna"],
];
//将ID作为新数组第一维的键
$arr3 = array_column($arr2, null, 'ID');
$arr3 = array_replace(array_flip($arr1), $arr3);
print_r(array_values($arr3));

//result
Array
(
    [0] => Array
        (
            [ID] => 2
            [Name] => Qandahar
        )

    [1] => Array
        (
            [ID] => 7
            [Name] => Haag
        )

    [2] => Array
        (
            [ID] => 10
            [Name] => Tilburg
        )

    [3] => Array
        (
            [ID] => 1
            [Name] => Kabul
        )

    [4] => Array
        (
            [ID] => 30
            [Name] => Delft
        )

    [5] => Array
        (
            [ID] => 9
            [Name] => Eindhoven
        )

    [6] => Array
        (
            [ID] => 53
            [Name] => Tafuna
        )

)
本作品采用《CC 协议》,转载必须注明作者和本文链接
附言 1  ·  5年前

根据评论里的大佬的指点有更优的方法:

$arr1 = [2, 7, 10, 1, 30, 9, 53];
$arr2 = [
    ["ID" => 1, "Name" => "Kabul"],
    ["ID" => 2, "Name" => "Qandahar"],
    ["ID" => 7, "Name" => "Haag"],
    ["ID" => 9, "Name" => "Eindhoven"],
    ["ID" => 10, "Name" => "Tilburg"],
    ["ID" => 30, "Name" => "Delft"],
    ["ID" => 53, "Name" => "Tafuna"],
];
$arr2 = array_column($arr2, null, 'ID');
foreach ($arr1 as &$v) {
    $v = $arr2[$v];
}
print_r($arr1);
Egfly
讨论数量: 4
╰ゝSakura

//将ID作为新数组第一维的键
array_walk($arr2, function ($item) use (&$arr3) {
$arr3[$item['ID']] = $item;
});

这个可以使用array_column($arr2, null, 'ID');

5年前 评论

因为id不同,可以使用将二维数组的id取出来作为这个数组的键值,然后foreach数组1


<?php
foreach($arr1 as &$v){
      $v = $arr2[$v];
}
5年前 评论
Egfly

@Marshall 学到了,还可以这样用的 :joy:

5年前 评论
Egfly

@mlover 嗯嗯,感谢,这样更优。

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!