Php 如何递归地迭代和编辑包含数组、类和对象的混合变量?

Php 如何递归地迭代和编辑包含数组、类和对象的混合变量?,php,recursion,multidimensional-array,iterator,Php,Recursion,Multidimensional Array,Iterator,我试图使用RecursiveIteratorIterator类并遍历每个子对象,以查看某些键是否与我拥有的特定列列表匹配。一旦键/列匹配,我将更改文本。但是,我想确保可以访问每个元素中都包含对象的多维数组 我希望找到一种方法来遍历数组和对象,然后遍历较低的子级并检查键名。如果键名匹配,我可能希望在其上运行回调函数或某种regex/replace函数 数据如下所示: [0] => Array ( [01__BLAH_A] => 1

我试图使用RecursiveIteratorIterator类并遍历每个子对象,以查看某些键是否与我拥有的特定列列表匹配。一旦键/列匹配,我将更改文本。但是,我想确保可以访问每个元素中都包含对象的多维数组

我希望找到一种方法来遍历数组和对象,然后遍历较低的子级并检查键名。如果键名匹配,我可能希望在其上运行回调函数或某种regex/replace函数

数据如下所示:



[0] => Array
        (
            [01__BLAH_A] => 1
            [01__BLAH_B] => 0
            [01__BLAH_C] => 1
            [01__BLAH_D] => 1
            [01__BLAH_E] => 1
            [01__BLAH_F] => 1
            [01__BLAH_G] => 0
            [01__BLAH_H] => 3
            [01__BLAH_I] => 0
            [01__BLAH_J] => 1
            [01__BLAH_K] => 1
            [01__BLAH_L] => 1
            [01__BLAH_M] => 3
            [SOME_OBJECT] => some_object Object
            (
                    [variable_1:some_type:private] => 
                    [variable_2:some_type:private] => 
                    [my_data:protected] => Array
                    (
                            [BLAH_1_A] => nAME
                            [BLAH_1_B] => blahblah
                            [BLAH_1_C] => other_dude
                            [BLAH_1_D] => 1
                            [BLAH_1_E] => 55
                            [BLAH_1_F] => 1
                            [BLAH_1_G] => null
                            [BLAH_1_H] => 1234567989
                    )

            )
        [SOME_OTHER_OBJECT] => some_other_object Object
            (
                    [variable_1:some_type:private] => 
                    [variable_2:some_type:private] => 
                    [my_data:protected] => Array
                    (
                            [BLAH_2_A] => nAME of another
                            [BLAH_2_B] => fofofofo
                            [BLAH_2_C] => right_dude
                            [BLAH_2_D] => 1
                            [BLAH_2_E] => 33
                            [BLAH_2_F] => 2
                            [BLAH_2_G] => 0
                            [BLAH_2_H] => 987654321
                    )
            )
        )
[1] => Array
        (
            [02__BLAH_A] => 1
            [02__BLAH_B] => 0
            [02__BLAH_C] => 1
            [02__BLAH_D] => 1
            [02__BLAH_E] => 1
            [02__BLAH_F] => 1
            [02__BLAH_G] => 0
            [02__BLAH_H] => 3
            [02__BLAH_I] => 0
            [02__BLAH_J] => 1
            [02__BLAH_K] => 1
            [02__BLAH_L] => 1
            [02__BLAH_M] => 3
            [SOME_OTHER_OBJECT] => some_other_object Object
            (
                    [variable_1:some_type:private] => 
                    [variable_2:some_type:private] => 
                    [my_data:protected] => Array
                    (
                            [BLAH_2_A] => nAME of another
                            [BLAH_2_B] => fofofofo
                            [BLAH_2_C] => right_dude
                            [BLAH_2_D] => 1
                            [BLAH_2_E] => 33
                            [BLAH_2_F] => 2
                            [BLAH_2_G] => 0
                            [BLAH_2_H] => 987654321
                    )
            )
        )
$new_text = Modifiable_Iterator::make($mixed_bag_of_data)->exec();
请注意,数据有一个基本的对象数组、一些元素和嵌套对象。每个数组元素中可能有不同的对象类型。我想要一个迭代器,它对所有这些元素都是不可知的

我以为我使用递归迭代器走上了正确的道路,但是当它到达那些对象时遇到了障碍

class Modifiable_Iterator
extends RecursiveIteratorIterator
{
    private $char_set;
    private $columns_to_check = array();

    static function make($mixed_array_data)
    {
        return new self($mixed_array_data); 
    }

    function __construct($data)
    {
        parent::__construct(
            new RecursiveArrayIterator($data), 
            RecursiveIteratorIterator::SELF_FIRST, 
            null);

        $this->columns_to_check = array('BLAH_2_A', 'BLAH_1_A');        
    }

    final public function current($parent_key_name = null)
    {
        // Retrieves the current value
        $current    = parent::current();

        if (in_array($this->key(), $this->columns_to_check))
        {
            // If the column name matches the list of columns in the private
            // variable, then edit the column value

            return _some_function_that_edits_this_value($current);
        }

        return $current;
    }

    final public function exec() 
    {
        $this->_loop_check($this);

        return $this;
    }

    final private function _loop_check($iterator)
    {
        while ($iterator->valid())
        {
            if ($iterator->hasChildren())
            {
                $this->_loop_check($iterator->getChildren());
            }

            $this->offsetSet($iterator->key(), $this->current());

            $iterator->next();
        }
    }    

    final private function _some_function_that_edits_this_value($value)
    {
        // Do something to the value and return it.

        return $value;
    }
}
我希望能够获取混合数据对象,然后尝试执行以下代码:



[0] => Array
        (
            [01__BLAH_A] => 1
            [01__BLAH_B] => 0
            [01__BLAH_C] => 1
            [01__BLAH_D] => 1
            [01__BLAH_E] => 1
            [01__BLAH_F] => 1
            [01__BLAH_G] => 0
            [01__BLAH_H] => 3
            [01__BLAH_I] => 0
            [01__BLAH_J] => 1
            [01__BLAH_K] => 1
            [01__BLAH_L] => 1
            [01__BLAH_M] => 3
            [SOME_OBJECT] => some_object Object
            (
                    [variable_1:some_type:private] => 
                    [variable_2:some_type:private] => 
                    [my_data:protected] => Array
                    (
                            [BLAH_1_A] => nAME
                            [BLAH_1_B] => blahblah
                            [BLAH_1_C] => other_dude
                            [BLAH_1_D] => 1
                            [BLAH_1_E] => 55
                            [BLAH_1_F] => 1
                            [BLAH_1_G] => null
                            [BLAH_1_H] => 1234567989
                    )

            )
        [SOME_OTHER_OBJECT] => some_other_object Object
            (
                    [variable_1:some_type:private] => 
                    [variable_2:some_type:private] => 
                    [my_data:protected] => Array
                    (
                            [BLAH_2_A] => nAME of another
                            [BLAH_2_B] => fofofofo
                            [BLAH_2_C] => right_dude
                            [BLAH_2_D] => 1
                            [BLAH_2_E] => 33
                            [BLAH_2_F] => 2
                            [BLAH_2_G] => 0
                            [BLAH_2_H] => 987654321
                    )
            )
        )
[1] => Array
        (
            [02__BLAH_A] => 1
            [02__BLAH_B] => 0
            [02__BLAH_C] => 1
            [02__BLAH_D] => 1
            [02__BLAH_E] => 1
            [02__BLAH_F] => 1
            [02__BLAH_G] => 0
            [02__BLAH_H] => 3
            [02__BLAH_I] => 0
            [02__BLAH_J] => 1
            [02__BLAH_K] => 1
            [02__BLAH_L] => 1
            [02__BLAH_M] => 3
            [SOME_OTHER_OBJECT] => some_other_object Object
            (
                    [variable_1:some_type:private] => 
                    [variable_2:some_type:private] => 
                    [my_data:protected] => Array
                    (
                            [BLAH_2_A] => nAME of another
                            [BLAH_2_B] => fofofofo
                            [BLAH_2_C] => right_dude
                            [BLAH_2_D] => 1
                            [BLAH_2_E] => 33
                            [BLAH_2_F] => 2
                            [BLAH_2_G] => 0
                            [BLAH_2_H] => 987654321
                    )
            )
        )
$new_text = Modifiable_Iterator::make($mixed_bag_of_data)->exec();
正在尝试:

让我们提供一个充满数据的实例:

$family = new YourClass(array(

        'name' => 'John',
        'surname' => 'Doe',
        'myAwesomeFriend' => new YourClass(array(

            'name' => 'Jane',
            'surname' => 'Doe'          

        ))

));
现在找到一种方法来抓取此数据:

// we search the $element for keys in $keyList, then call the $callback eventually
function map($callback, $element, $keyList){

    foreach($element as $key => &$value)
    {

        //if we need to iterate on the field, we do again
        if($value instanceof ArrayIterator)
            map($callback, $value, $keyList);

        // else if key is in given keylist, we apply callback
        else if( in_array( $key, $keyList) )
            $value = call_user_func($callback, $value);

    }

}
$family
上使用此功能,搜索名为
name
的键并将值转换为小写:

map(function($element){

    return strtolower($element);

}, $family, array('name'));
让我们看一下
var\u dump($family)
打印出的内容:

object(YourClass)#1 (1) {
  ["storage":"ArrayIterator":private]=>
  array(3) {
    ["name"]=>
    string(4) "john"
    ["surname"]=>
    string(3) "Doe"
    ["myAwesomeFriend"]=>
    object(YourClass)#2 (1) {
      ["storage":"ArrayIterator":private]=>
      array(2) {
        ["name"]=>
        string(4) "jane"
        ["surname"]=>
        string(3) "Doe"
      }
    }
  }
}
放下箱子,任务完成


警告:您的对象/子对象需要扩展
ArrayIterator
——如果您不喜欢,您必须手动实现它的许多接口[
Iterator
ArrayAccess
,等等。

到目前为止,这是我提出的,它适用于所有对象,但不适用于单个数组元素。使用反射修改对象时,数据将保留

我当前执行此操作的代码段仍然与我最初的概念相似:

Replacer::make($mixed_data_array)->exec();
下面是我写的代码。在大多数情况下,我的所有嵌套对象都会按预期进行更改,并返回到$mixed_datay_数组变量。我正在使用迭代器的offsetSet()方法修改的所有其他数组元素都没有存储。不确定我是否需要使用“神奇&”,这似乎不适合这个场景。。。还是我需要再做一次反思?救命啊

(代码如下)

类替换程序
扩展递归迭代器
{
私人$char_集;
private$char_set_exclude=array();
私有$columns_to_check=array();
私有$columns_,_titles=array();
私人数据;
私人$title_前缀;
静态函数make($mixed\u array\u data)
{
回归自我(
是否为空($mixed\u array\u data)?array():$mixed\u array\u data);
}
函数构造($data)
{
父项::_构造(新的递归ArrayIterator($data),
递归迭代器::SELF_优先,
无效);
$this->char_set='abcdefghijklmnopqrstuvxyz'
“abcdefghijklmnopqrstuvxyz”;
$this->char\u set\u exclude=
数组(“@”,
' ',
'.');
$this->columns\u to\u check=
数组('电子邮件地址',
“成员名称”);
$this->data=$data;
}
最终公共函数替换_文本($key,$value)
{
if(是_数组($value))
{
返回$value;
}
$new_text=null;
if(在数组中(strtolower($key),$this->columns\u to\u check))
{
$cypher=str\u shuffle($this->char\u set);
//字符串中的每个字符都将替换为无序文本。
对于($i=0;$ichar\u set\u exclude))
{
$new_text.=$value[$i];
}
其他的
{
$new_文本=
$cypher[strpos($this->char_set,$value[$i]);
}
}
}
其他的
{
$new_text=$value;
}
返回$new_text;
}
最终公共职能执行官()
{
$this->revind();
如果(!$this->valid())
{
返回$this->process\u child\u对象($this->data);
}
返回$this->begin_replace($this)->get_data();
}
最终公共函数get_data()
{
返回$this->data;
}
最终公共函数集\u列\u到\u检查($columns\u数组)
{
如果(!is_数组($columns_数组)&&!empty($columns_数组)
{
$columns\u array=array($columns\u array);
}
$this->columns\u to\u check=$columns\u数组;
退还$this;
}
最终私有函数开始替换($data)
{
而($data->valid())
{
//如果存在任何子图元,请对子对象重复此过程。
如果($data->hasChildren())
{
$this->begin_replace($data->getChildren());
}
如果(是对象($data->current())
{
//如果当前元素是对象,请对其进行处理
//不同的是:使用Refelection
$this->process\u child\u对象($data->current());
}
其他的
{
//如果需要,使用内置偏移集方法更新数据键
//数组元素不在私有/受保护对象中,并且
//键名也位于列\u到\u检查数组中。
$data->offsetSet(
$data->key(),
$this->replace_text($data->key(),$data->current());
}
$data->next();
}
返回$data;
}
最终私有函数进程\子对象\对象($object)
{
如果(!is_object($object))