Php 使用数组\u walk\u递归但拒绝特定值的筛选器数组

Php 使用数组\u walk\u递归但拒绝特定值的筛选器数组,php,recursion,filter,Php,Recursion,Filter,我正在尝试筛选数组 $array = [ [ 'id' => 1, 'some_key' => 'some_value', 'attribute' => [ 'id' => 45, 'cat_id' => 1 ], 'sub' => [ 'id' => 17, 'some_

我正在尝试筛选数组

$array = [
    [
        'id' => 1,
        'some_key' => 'some_value',
        'attribute' => [
            'id' => 45,
            'cat_id' => 1
        ],
        'sub' => [
            'id' => 17,
            'some_key' => 'some_value',
            'attribute' => [
                'id' => 47,
                'cat_id' => 17
            ],
        ],
    ],
    [
        'id' => 2,
        'some_key' => 'some_value',
        'sub' => [
            'id' => 19,
            'some_key' => 'some_value',
        ],
    ]
];

$childArray = [];
array_walk_recursive($array, static function($value, $key) use(&$childArray){
    if($key === 'id') {
        $childArray[] = $value;
    }
});
这将返回一个包含所有以id为键的数组字段的数组

但是有一个小问题,一些数组有一个名为attribute的键,其中包含一个我不想要的idkey字段

[1,17,2,19] //this is what I want
有没有一种方法可以说不要在属性中使用id

在我当前的解决方案中,我在过滤器之前添加了一个过滤器:D


但这似乎不是最佳实践^^

您可以手动递归遍历,而不是递归遍历数组,并避免在属性键下进行所有遍历


演示:

您可以手动递归遍历,而不是递归遍历数组,并避免属性键下的所有遍历


演示:

找到一个可以展平阵列的函数。结果应该是这样的我有一个这样的类:

array (
  0 => 
  array (
    'id' => 1,
    'some_key' => "some_value",
    'attribute.id' => 45,
    'attribute.cat_id' => 1,
    'sub.id' => 17,
    'sub.some_key' => "some_value",
    'sub.attribute.id' => 47,
    'sub.attribute.cat_id' => 17,
  ),
  1 => 
  array (
    'id' => 2,
    'some_key' => "some_value",
    'sub.id' => 19,
    'sub.some_key' => "some_value",
  ),
)
因此,您拥有所有可用的密钥,并且可以使用修改后的数组。\u walk

$childArray = [];
array_walk_recursive($data, static function($value, $key) use(&$childArray){
    $keys = array_reverse(explode(".",$key));
    if($keys[0] === 'id' AND (!isset($keys[1]) OR $keys[1] != 'attribute')) {
        $childArray[] = $value;
    }
});
递归ArrayIterator类在数组值​​将根据键和值收集​​在不同层次上

$result = [];
$it =  new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($it as $key => $value) {
  $parentLevel = $it->getDepth()-1;
  $parentKey = $it->getSubIterator($parentLevel)->key();
  if($key === 'id' AND $parentKey !== 'attribute'){
    $result[] = $value;
  }
}

var_export($result);
//array ( 0 => 1, 1 => 17, 2 => 2, 3 => 19, )

找到一个可以展平阵列的函数。结果应该是这样的我有一个这样的类:

array (
  0 => 
  array (
    'id' => 1,
    'some_key' => "some_value",
    'attribute.id' => 45,
    'attribute.cat_id' => 1,
    'sub.id' => 17,
    'sub.some_key' => "some_value",
    'sub.attribute.id' => 47,
    'sub.attribute.cat_id' => 17,
  ),
  1 => 
  array (
    'id' => 2,
    'some_key' => "some_value",
    'sub.id' => 19,
    'sub.some_key' => "some_value",
  ),
)
因此,您拥有所有可用的密钥,并且可以使用修改后的数组。\u walk

$childArray = [];
array_walk_recursive($data, static function($value, $key) use(&$childArray){
    $keys = array_reverse(explode(".",$key));
    if($keys[0] === 'id' AND (!isset($keys[1]) OR $keys[1] != 'attribute')) {
        $childArray[] = $value;
    }
});
递归ArrayIterator类在数组值​​将根据键和值收集​​在不同层次上

$result = [];
$it =  new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($it as $key => $value) {
  $parentLevel = $it->getDepth()-1;
  $parentKey = $it->getSubIterator($parentLevel)->key();
  if($key === 'id' AND $parentKey !== 'attribute'){
    $result[] = $value;
  }
}

var_export($result);
//array ( 0 => 1, 1 => 17, 2 => 2, 3 => 19, )

要返回符合条件的ID而不是创建引用变量,请在迭代时合并函数的递归调用

代码:

输出:

array (
  0 => 1,
  1 => 17,
  2 => 2,
  3 => 19,
)

要返回符合条件的ID而不是创建引用变量,请在迭代时合并函数的递归调用

代码:

输出:

array (
  0 => 1,
  1 => 17,
  2 => 2,
  3 => 19,
)

使用array_walk_recursive很难做到这一点,因为它只访问叶键值。使用array_walk_recursive很难做到这一点,因为它只访问叶键值。这个解决方案的想法很好,但这会迫使我在数组中运行几次。这正是我想要避免的:但是思想还是+1,赞美还是+1。如今,编写可理解的代码比在执行时节省一微秒更重要。我添加了一个变体。我喜欢看到总是有几种方法来实现罗马:D使用迭代器也是一种很好的可能性。这个解决方案的想法很好,但这会迫使我在数组中运行几次。这正是我想要避免的:但是思想还是+1,赞美还是+1。如今,编写可理解的代码比在执行时节省一微秒更重要。我添加了一个变体。我喜欢看到总是有几种方法可以到达罗马:D使用迭代器也是一种很好的可能性。