【问题标题】:Iterate multidimensional Array recursively and return same array structure and inserting new key/values in PHP递归迭代多维数组并返回相同的数组结构并在 PHP 中插入新的键/值
【发布时间】:2015-10-02 08:59:03
【问题描述】:

我正在尝试编写一个 sn-p,它采用多维数组并在找到命名搜索键的同一级别插入一些键。 我不必依赖数组的结构(但最多5个级别) 我不能使用通过引用传递,所以传统的循环函数对这种方法没有帮助。

我有 2 个选项:SPL 或重新构造数组并沿途改变它的递归

使用 SPL,我似乎无法插入新值..

            $a= new \ArrayObject($priceConfig);
            $array = new \RecursiveArrayIterator($a);
            $iterator = new \RecursiveIteratorIterator($array, \RecursiveIteratorIterator::SELF_FIRST);
            foreach ($iterator as $key => $value) {
                if (is_array($value) && $key == 'prices') {
                    $iterator->offsetSet('myPrice',['amount'=>'1.00']);
                }
            }

            print_r($a->getArrayCopy());

它不会在所需级别插入新密钥,但它会循环遍历数组..我错过了什么?

重构数组并在嵌套数组中的关键字搜索中插入新值的递归函数有效,但我想使用迭代器来执行此操作..

             function recursive( $input, $searchKey, $key=null) {
                $holder = array();
                if(is_array( $input)) {
                    foreach( $input as $key => $el) {
                        if (is_array($el)) {
                            $holder[$key] = recursive($el, $searchKey, $key);
                            if ($key == $searchKey) {
                                $holder[$key]['inertedPrice'] = "value";
                            }
                        } else {
                            $holder[$key] = $el;
                        }
                    }
                }
                return $holder;
            }

INPUT(总是有一些“X 级别的价格键和结构”)

    [1] => Array
        (
            [1] => Array
                (
                    [prices] => Array
                        (
                            [onePrice] => Array( [amount] => 10)
                            [finalPrice] => Array ([amount] => 10)
                        )
                    [key1] => value2
                    [key2] => value2
                )

            [2] => Array
                (
                    [prices] => Array
                        (
                            [otherPrice] => Array([amount] => 20)
                            [finalPrice] => Array([amount] => 20)
                        )
                    [key] => value
                )
        )
)

输出

[1] => Array
    (
        [1] => Array
            (
                [prices] => Array
                    (
                        [onePrice] => Array( [amount] => 10)
                        [finalPrice] => Array ([amount] => 10)
                        [INSERTEDPrice] => Array([amount] => value)
                    )
                [key1] => value2
                [key2] => value2
            )

        [2] => Array
            (
                [prices] => Array
                    (
                        [otherPrice] => Array([amount] => 20)
                        [finalPrice] => Array([amount] => 20)
                        [INSERTEDPrice] => Array([amount] => )
                    )
                [key] => value
            )
    )

)

【问题讨论】:

  • 请包含示例输入和输出,以便我们更好地理解问题。
  • 添加所需的输出并提供输入

标签: php arrays recursion multidimensional-array spl


【解决方案1】:

您可以通过使用自定义迭代器逻辑扩展 RecursiveArrayIterator 来使用迭代器:

class Foo extends RecursiveArrayIterator
{
    public function getChildren()
    {
        if ($this->key() == 'prices') {
            return new self(array_merge($this->current(), ['foo' => 'bar']));
        } else {
            return parent::getChildren();
        }
    }
}

【讨论】:

    【解决方案2】:

    您可以使用 foreach 循环和递归等基本工具相当轻松地解决问题。这是一个这样的解决方案。

    function mergeWithKey($targetKey, $new, array $array) {
      foreach ($array as $key => $value) {
        if ($key === $targetKey) {
          $array[$key] = array_merge($array[$key], $new);
        }
        elseif (is_array($value)) {
          $array[$key] = mergeWithKey($targetKey, $new, $value); 
        }
      }
      return $array;
    }
    
    // Example
    $output = mergeWithKey('prices', array('INSERTEDPrice' => 'value'), $input);
    

    简单地说,当我们遍历数组时,如果我们找到了我们正在寻找的键,那么我们就会合并新的价格。如果我们改为找到一个子数组,那么我们会将新价格合并到该子数组中。

    我通过保留关键“价格”作为参数来努力概括该功能。这可能仍然是一个不太可能重用的不稳定功能。

    使用一些常用算法,您可以很好地构建此功能,而且您可以重复使用这些算法。一种是用key和value同时映射数组,另一种是将二维数组展平为一维数组。

    function arrayMapWithKey(callable $f, array $array) {
      $out = array();
      foreach ($array as $key => $value) {
        $out[$key] = $f($key, $value);
      }
      return $out;
    }
    
    function concat(array $array) {
      if (empty($array)) {
        return array(); 
      }
      else {
        return call_user_func_array('array_merge', $array);
      }
    }
    

    这些定义使您能够编写替代解决方案。

    function addPrice($name, $price, $data) {
      return concat(arrayMapWithKey(
        function ($k, $v) use ($name, $price) {
          if ($k === 'prices') {
            return array($k => array_merge($v, array($name => $price)));
          }
          elseif (is_array($v)) {
            return array($k => addPrice($name, $price, $v));  
          }
          else {
            return array($k => $v);
          }
        },
        $data
      ));
    }
    

    arrayMapWithKey 的另一个公式是复制带有值的键,然后使用常规的 array_map

    function arrayWithKeys(array $array) {
      $out = array();
      foreach ($array as $key => $value) {
        // in PHP arrays are often used as tuples,
        // and here we have a 2-tuple.
        $out[] = array($key, $value);
      }
      return $out;
    }
    

    【讨论】:

    • 我会选择你的答案,因为它更完整,我也喜欢 SPL 的答案,更多的是 OOP vs Alghoritms
    猜你喜欢
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多