将对象保留在一个 objectArray 中,这些对象在另一个 objectArray 中找到了 id 值

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

我正在尝试使用

array_filter()
来过滤对象数组,它们共享一个共同的值,即
warehouse_id

$warehouse_1 = new warehouse(1, 100, [1,2,3,4]);
$warehouse_2 = new warehouse(2, 1100, [1,2,3,4]);
$warehouse_3 = new warehouse(3, 12000, [1,2,3,4]);
$warehouse_4 = new warehouse(4, 130000, [1,2,3,4]);
$warehouse_5 = new warehouse(5, 1400000, [1,2,3,4]);

$inventory_feed_1 = new inventory_feed(12, 1, "2as21332kjd");
$inventory_feed_2 = new inventory_feed(10, 2, "2123asagfrtsdd");
$inventory_feed_3 = new inventory_feed(11, 3, "2as1231sds2d");
$inventory_feed_4 = new inventory_feed(13, 4, "2as1231sds2d");
$inventory_feed_5 = new inventory_feed(14, 5, "2as1231sds2d");

$ifeeds = ["a" => $inventory_feed_1, "b" => $inventory_feed_2, "c" => $inventory_feed_3];
$warehouses = [$warehouse_1, $warehouse_2, $warehouse_3, $warehouse_4, $warehouse_5];

$warehouses_filtered = array_filter(
  $warehouses,
  function ($warehouse) use ($ifeeds) {
    foreach($ifeeds as $ifeed_id => $ifeed) {
      return $ifeed->getWarehouseId() == $warehouse->getId();
  });

echo count($warehouses_filtered);

所需的输出应该是

[$warehouse_1, $warehouse_2, $warehouse_3]
但它总是返回给我原来的(
5
)

php arrays object filtering intersection
2个回答
1
投票

您将返回

foreach
循环的第一次迭代,因此您只是测试仓库是否与第一个 feed 匹配。

一旦找到匹配项,您就应该返回 true,但在完成循环而没有找到匹配项之前,不要返回 false。

$warehouses_filtered = array_filter(
  $warehouses,
  function ($warehouse) use ($ifeeds) {
    foreach($ifeeds as $ifeed_id => $ifeed) {
      if ($ifeed->getWarehouseId() == $warehouse->getId()) {
        return true;
      }
    }
    return false;
  });

演示


0
投票

为了避免在嵌套结构内进行过多的方法调用,请通过从 feeds 数组填充仓库 ID 的查找/映射来为过滤过程做好准备。效率/时间复杂度会很好,因为只执行两个线性循环。

代码:(演示

$feedMap = array_fill_keys(
    array_map(fn($obj) => $obj->getWarehouseId(), $ifeeds), // use ids as keys
    true // this could by any non-null value
);

$warehouses_filtered = array_filter(
    $warehouses,
    fn($warehouseObj) => isset($feedMap[$warehouse->getId()]) // keep if in the lookup
);

var_export($warehouses_filtered);

或者,如果您想在没有任何临时地图的情况下完成此操作并希望使用本机交集函数,那么

array_uintersect()
是最好的工具。 (演示)

var_export(
    array_uintersect(
        $warehouses,
        $ifeeds,
        fn($a, $b) => (method_exists($a, 'getId') ? $a->getId() : $a->getWarehouseId())
                      <=>
                      (method_exists($b, 'getId') ? $b->getId() : $b->getWarehouseId())
    )
);

上面的两个片段都将返回相同的结果,这是一个仓库对象数组,其中包含在

$ifeeds
objectArray 中作为仓库 ID 找到的 id。

© www.soinside.com 2019 - 2024. All rights reserved.