返回

对象数组过滤技巧:正确使用 array_filter() 基于特定属性过滤

php

使用 array_filter() 过滤拥有特定 id 值的对象

问题概述

在使用 array_filter() 过滤对象数组时,如果你想基于对象的某个属性(例如 warehouse_id)进行过滤,可能会遇到意想不到的结果。这篇文章将探讨如何正确使用 array_filter() 来解决此问题,并提供一个清晰的代码示例。

解决方案

array_some()

为了在 array_filter() 中基于对象的属性进行过滤,我们可以利用 array_some() 函数。array_some() 接收一个数组和一个回调函数,如果数组中至少一个元素满足回调函数的条件,则返回 true

示例代码

$warehouses = [
    new Warehouse(1, 100, [1, 2, 3, 4]),
    new Warehouse(2, 1100, [1, 2, 3, 4]),
    new Warehouse(3, 12000, [1, 2, 3, 4]),
    new Warehouse(4, 130000, [1, 2, 3, 4]),
    new Warehouse(5, 1400000, [1, 2, 3, 4]),
];

$ifeeds = [
    12 => new InventoryFeed(12, 1, "2as21332kjd"),
    10 => new InventoryFeed(10, 2, "2123asagfrtsdd"),
    11 => new InventoryFeed(11, 3, "2as1231sds2d"),
    13 => new InventoryFeed(13, 4, "2as1231sds2d"),
    14 => new InventoryFeed(14, 5, "2as1231sds2d"),
];

$warehouses_filtered = array_filter(
    $warehouses,
    fn($warehouse) => array_some(
        $ifeeds,
        fn($ifeed) => $ifeed->getWarehouseId() === $warehouse->getId()
    )
);

echo count($warehouses_filtered); // 3

改进后的代码

改进后的代码使用箭头函数简化了代码并提高了可读性。

常见问题解答

1. 为什么原始的 array_filter() 无法按预期工作?

原始的 array_filter() 中的匿名函数返回一个布尔值,表示元素是否应该包含在结果数组中。由于内部循环永远不会遇到与当前 warehouse 对象的 id 匹配的 ifeed 元素,因此该匿名函数总是返回 false,导致过滤后数组为空。

2. array_some() 在这里是如何工作的?

array_some() 遍历 ifeeds 数组,并检查每个元素是否满足条件:$ifeed->getWarehouseId() === $warehouse->getId()。如果至少一个元素满足此条件,则 array_some() 返回 true

3. 为什么使用箭头函数?

箭头函数是一种简洁且更易读的语法,用于编写匿名函数。它们消除了 function 和大括号,并允许使用更简洁的表达式。

4. 是否可以在一个回调函数中使用多个 array_some()

可以。你可以根据需要在回调函数中嵌套多个 array_some()

5. 如何提高 array_filter() 的性能?

对于大型数组,可以考虑使用 array_map()array_reduce() 等更有效的方法进行过滤。