我有以下问题:
我有一个数组的数组包含未知数量的子数组所以我的数组可能是这样的
array('element1'=>array('subelement1'=>'value'
'subelement2'=>array(...),
'element2'=>array('something'=>'this',
'subelement1'=>'awesome'));
现在我想写一个函数,它能够通过在数组中拥有一个值的路径来替换它,第一个参数是一个数组,它定义了要搜索的键。如果我想用'anothervalue'替换示例中的'value',函数调用应该像这样:
replace_array(array('element1','subelement1'),'anothervalue');
它还应该能够通过使用null或其他占位符来替换给定关卡上的所有值,例如
replace_array(array(-1, 'subelement1'),'anothervalue');
应该替换'value'和'awesome'。
我试图通过使用递归函数和引用来让它工作(一次调用通过使用path变量中的第一个元素搜索第一个数组,然后使用子数组再次调用自己,直到找到给定路径定义的所有事件)。
有没有聪明的方法来完成它?因为我的参考意见似乎不太奏效。
我可以稍后发布我正在使用atm的代码。
谢谢。
edit:我更新了我的答案,也做-1
edit:由于-1
可以作为数组键使用,我认为您不应该使用它来标记"所有"键。然而,数组本身不能用作数组键。因此,代替-1
,我选择使用数组([]
或array()
)来标记"所有"键。
function replace_array(&$original_array, $path, $new_value) {
$cursor =& $original_array;
if (!is_array($path))
return;
while($path) {
$index = array_shift($path);
if (!is_array($cursor) || (!is_array($index) && !isset($cursor[$index])))
return;
if (is_array($index)) {
foreach($cursor as &$child)
replace_array($child, $path, $new_value);
return;
} else {
$cursor =& $cursor[$index];
}
}
$cursor = $new_value;
return;
}
// use like : replace_array($my_array, array("first key", array(), "third key"), "new value");
// or php5.4+ : replace_array($my_array, ["first key", [], "third key"], "new value");
构造这个方法的关键在于通过引用传递数组。如果你这样做,任务就会变得非常简单。
这将是一个递归方法,所以问题应该是:
- 这是最后一次递归吗?
- 在这个关卡中我需要寻找什么键?
array_shift()
在这里很有用,当你得到第一级时,同时为下一个递归适当地缩短$searchPath
。
function deepReplace($searchPath, $newValue, &$array) {
// ^- reference
//Is this the last recursion?
if (count($searchPath) == 0) {
$array = $newValue;
}
if (!is_array($array))
return;
//What key do I have to look for in this level?
$lookFor = array_shift($searchPath);
//To support all values on given level using NULL
if ($lookFor === null) {
foreach ($array as &$value) {
// ^- reference
deepReplace($searchPath, $newValue, $value);
}
} elseif (array_key_exists($lookFor, $array)) {
deepReplace($searchPath, $newValue, $array[$lookFor]);
}
}
看到它在这里工作,像
deepReplace(array(null, "subelement1"), "newValue", $data);
deepReplace(array("element1", "subelement1"), "newValue", $data);