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