【问题标题】:Get original array structure from RecursiveIteratorIterator instance从 RecursiveIteratorIterator 实例获取原始数组结构
【发布时间】:2023-03-09 07:56:01
【问题描述】:

设置:

$array = ['level_one' => [
        'level_two' => [
            'level_three' => [
                'key' => 1
            ]
        ]
    ]];

我为需要遍历每个单独值的过滤过程做准备:

$recurIter = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));

问题:

过滤过程完成后,我想将过滤后的 $recurIter 转换回具有原始结构的数组。我该怎么做?

目前尝试过:

iterator_to_array($recurIter)

这将返回展平的初始数组:

数组 ( [键] => 1 )

我想要原始结构 iterator_to_array 仅在应用于 RecursiveArrayIterator 实例时返回原始数组结构

谢谢

【问题讨论】:

  • 你能描述一下“过滤过程”吗?在使用RecursiveIteratorIterator 展平迭代之前进行过滤通常更有意义,例如通过将RecursiveArrayIterator 包裹在CallbackFilterIterator 中。
  • 这是一个简单的过滤过程,我在其中取消设置不匹配的值。我正在使用 RecursiveIteratorIterator 因为我不知道结构有多深。除了编写我自己的递归迭代器来跟踪结构之外,我不知道另一种方法

标签: php arrays spl


【解决方案1】:

我有同样的需求,但我还没有找到解决方案。

所以我已经建立了自己的功能,也许有人需要它

        $array = ['level_one' => [
              'level_two' => [
                    'level_three' => [
                         'key' => 1
                    ]
              ]
         ]];                

        $new_array = array();

        function copy_recursive(&$new_array,$array){

            $current =& $new_array;
            foreach($array as $key => $val){
                //you can also change here the original key name if you want
                if (!isset($current[$key])) $current[$key] = array();
                if(is_array($val)){
                    copy_recursive($current[$key],$val);
                }else{
                    //you can check or manipulate here the original value if you need
                    $current[$key] = $val;
                }
            }                   
        }

        copy_recursive($new_array,$array);

返回 $new_array 与原始 $array 具有相同的结构,但这不是从一个数组到另一个数组的简单复制。

您可以为每个key 应用您的代码 => value 并将其保存在具有相同结构的$new_array

【讨论】:

    【解决方案2】:

    这行得通吗?

    iterator_to_array($recurIter, FALSE)

    编辑:

    如果您正在进行过滤,您可能对此感兴趣:

    /**
     * Select part of a data structure.
     *
     * @param array|object $data
     *   The input data to search.
     * @param callable $callback
     *   The callback
     *   $value - the value of the iterator.
     *   $key - the key of the iterator.
     *   $iterator - the iterator can be used to compare against depth + other info.
     * @param int $flag
     *   Flags for RecursiveIteratorIterator -
     *   http://php.net/manual/en/class.recursiveiteratoriterator.php#recursiveiteratoriterator.constants.
     * @param bool $preserve_keys
     *   If false the returned array of results will have its keys re-indexed
     *   If true the original keys are kept but duplicate keys can be overwritten.
     *
     * @return array
     *   Filtered array.
     */
    function recursive_select($data, callable $callback, $flag = \RecursiveIteratorIterator::SELF_FIRST, $preserve_keys = FALSE) {
    
      return iterator_to_array(new \CallbackFilterIterator(new \RecursiveIteratorIterator(new \RecursiveObjectIterator($data), $flag), $callback), $preserve_keys);
    }
    

    用法:

    $selection = recursive_select($array, function ($value, $key, $iterator) : bool {
      return $iterator->getDepth() == 2;
    });
    

    $selection = recursive_select($array, function ($value, $key, $iterator) : bool {
      return $key == 'level_two';
    });
    

    基本上你想要什么条件,不要因为性能而尝试在大型数据集上执行此操作,如果你需要大规模数据过滤,请尽可能使用 SQL,但首先使用潮汐/xhprof 进行基准测试

    第二次编辑: 我没有看到您希望在过滤器 array_walk_recursive() 可能对您有所帮助后保留结构

    【讨论】:

    • iterator_to_array($recurIter, FALSE) 不起作用,我得到了由 ints 索引的扁平数组结构
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 2016-09-30
    • 1970-01-01
    相关资源
    最近更新 更多