在PHP中用其他数组值循环遍历对象数组[duplicate]

6yoyoihd  于 2023-03-16  发布在  PHP
关注(0)|答案(2)|浏览(131)

此问题在此处已有答案

Keep array rows where a column value is found in a second flat array(4个答案)
8小时前关门了。
在下面的示例中,目标是根据一个数组从另一个数组中选择某些元素(选择id):

$cars = [
    0 =>  ["id" => 1, "name" => "FORD"],
    1 =>  ["id" => 2, "name" => "BMW"],
    2 =>  ["id" => 3, "name" => "FIAT"],
    3 =>  ["id" => 4, "name" => "RENAULT"],
    4 =>  ["id" => 5, "name" => "BENTLEY"],
];

包含ID选择的数组:

$selection = [
    0 => "1",
    1 => "3",
    2 => "4"
]

预期产出:

$cars = [
    0 =>  ["id" => 1, "name" => "FORD"],
    1 =>  ["id" => 3, "name" => "FIAT"],
    2 =>  ["id" => 4, "name" => "RENAULT"],
];

尝试举例说明:

$result = array();
foreach($cars as $key => $val) {
    if ($val['id'] === $selection[$key]) {
        $result[] = $cars[$key];
    }
}
8ehkhllq

8ehkhllq1#

你可以利用php的数组filter函数。
主要的“技巧”是遍历所有的汽车,检查它们对应的ID是否在选择中。array_filter()需要一个数组和一个函数。函数检查当前的汽车ID是否是选择的一部分。当filter函数返回true时,保留该值,否则丢弃该值。
您也可以反过来,或者使用两个嵌套的foreach循环来创建一个新数组,但这样做更简单。
Online Demo

$carsBySelection = array_filter($cars, function($car) use ($selection) {
    return in_array($car["id"], $selection);
});

print_r($carsBySelection);
Array
(
    [0] => Array
        (
            [id] => 1
            [name] => FORD
        )

    [2] => Array
        (
            [id] => 3
            [name] => FIAT
        )

    [3] => Array
        (
            [id] => 4
            [name] => RENAULT
        )

)
5fjcxozz

5fjcxozz2#

虽然使用array_filter的答案肯定可以完成工作,但它涉及到每次迭代时的in_array函数调用。对于小数据,这不是问题。对于较大的数据集,在一次迭代中重复的函数调用可能会导致性能下降。在可能的情况下,最好“预处理”数据,以便使用 * 语言构造 * 代替 * 函数 * 进行更轻松的操作。
您可以使用array_flip($selection)“启用”索引查找,即通过交换键和值,然后执行简单的键查找:对于较大的数据,isset($selection[$id])的性能明显优于in_array($id, $selection),我们实际上只关心(唯一的)密钥。
作为过滤的替代方法,您可以使用array_column() * 按所需键重新索引数组 *,其中null用于列键(返回完整数组),id用于索引键:

$cars_by_id = array_column($cars, null, 'id');

然后,我们就差一个array_intersect_key就可以从 *source数组 * 中提取 selection 了:

$selected_cars = array_intersect_key($cars_by_id, array_flip($selection));

在这里我们翻转$selection以交叉键。结果如预期。请参见此方法的演示。最后,这里是一个不带丢弃变量的一行程序(格式便于阅读):

$selected_cars = array_intersect_key(
    array_column($cars, null, 'id'), 
    array_flip($selection)
);

注意:生成的数组将以汽车的实际id作为索引键;而不是默认的零索引键。如果稍后在代码中用源数组交叉引用选定的汽车,请记住这一点;并且可能从一开始就通过适当的ID来索引汽车。

比较两种方法:array_filter()导致$cars的1次迭代,每个数组成员1次函数调用;然后,$selection的迭代次数与汽车的数量相同,in_array函数调用将每个$selection成员与当前汽车ID进行比较。

这个答案中的方法1.在$cars上迭代一次,用于简单的重新索引;2.对于键/值翻转,在$selection上迭代一次;然后3.针对交集迭代每个列表的关键字(AFAIK对两个列表排序,然后并行比较它们)。
P.S.当然,简单的foreach循环也可以工作。要修复您的初始尝试,如下所示:

$selection = array_flip($selection);

foreach($cars as $key => $val) {
    if (isset($selection[$val['id']])) {
        $result[] = $cars[$key];
    }
}

我会在需要“基本”性能的重要数据集(或较长的比较列表)中使用此方法(如果有人比较了PHP 8.x中的这些方法,请分享结果)。

相关问题