我有一个菜单数组,它是一个多维数组,我想对每个项目做一些事情,所以我尝试了array_walk_recursive。这是菜单:
$menu = array(
array(
'name'=>'a',
'url'=>'b',
),
array(
'name'=>'c',
'url'=>'d',
'children'=>array(
array(
'name'=>'e',
'url'=>'f'
)
)
)
);
但是array_walk_recursive只让我处理每一个元素,而不是数组。
array_walk_recursive($menu, function(&$item){
var_dump($item);//return a;b;c;d;e;f;g
});
我想要的是这样的:
array_walk_recursive_with_array($menu, function(&$item){
var_dump($item);//return array('name'=>'a','url'=>'b');a;b;array('name'=>'c',...);c;d;...
if(is_array($item) && isset($item['name'])){
// I want to do something with the item.
}
})
是否有任何PHP本机功能实现?
答案 0 :(得分:0)
根据array_walk_recursive documentation,你无法得到内部数组键。 实现需求的一种方法是使用array_walk并创建自己的递归。
function HandleArray(&$value){
if(is_array($value)){
//Do something with all array
array_walk($value,'HandleArray');
}
else{
//do something with your scalar value
}
}
array_walk(array($your_array),'HandleArray');
答案 1 :(得分:0)
@artragis 示例中使用 array_walk()
的无限递归保护似乎是必要的。
一个 ArrayHelper 类示例,用于将给定数组减少为给定数组键的数组值:
class ArrayHelper {
/**
* arrayFlattenToKeyValues - Like finding keys with array_walk_recursive()
* without the restriction "Any key that holds an array will not be passed to the function"
* @see https://www.php.net/manual/en/function.array-walk-recursive.php#refsect1-function.array-walk-recursive-examples
* @param array $deepArray
* @param string $fromKey
* @param int $maxDepth default = 10
* @param array $accumulator default = []
*
* @return array
*/
public static function arrayFlattenToKeyValues(
array $deepArray,
string $fromKey,
int $maxDepth = 10,
array $accumulator = []
): array {
array_walk($deepArray, function ($value, $key) use (&$accumulator, $fromKey, $maxDepth) {
if ($key === $fromKey) {
$accumulator[] = $value;
}
if ($maxDepth > 0 && is_array($value)) {
$accumulator = self::arrayFlattenToKeyValues($value, $fromKey, $maxDepth - 1, $accumulator);
}
});
return $accumulator;
}
}
这可能可以改进、简化或以不同的方式完成;请做!
答案 2 :(得分:-2)
这是一个基本的实用程序,递归自定义函数:
代码:(Demo)
function recurseAll($node) {
echo "\n---\n";
if (is_iterable($node)) {
var_export($node);
foreach ($node as $childNode) {
recurseAll($childNode);
}
} else {
echo $node;
}
}
array_walk($array, 'recurseAll');
// array_walk() avoids printing the entire parent array to screen as the first element
输出:
---
array (
'name' => 'a',
'url' => 'b',
)
---
a
---
b
---
array (
'name' => 'c',
'url' => 'd',
'children' =>
array (
0 =>
array (
'name' => 'e',
'url' => 'f',
),
),
)
---
c
---
d
---
array (
0 =>
array (
'name' => 'e',
'url' => 'f',
),
)
---
array (
'name' => 'e',
'url' => 'f',
)
---
e
---
f
为弄清楚artragis的答案可能是什么,... array_walk_recursive()
确实提供了对键和值的访问,但是仅在给定值是“标量”(非-迭代)。手册将这些标量值称为“叶节点”。
对于那些不熟悉本机php函数的人来说,另一个重要的注意事项是,尽管它保持键-值关联,但实际上并没有深度。换句话说,您将无法unset()
元素,也无法区分当前元素所在的当前级别。
我的代码段将打印所有可迭代和不可迭代的数据,优先级是在继续迭代当前级别之前更深地递归。
我不确定您要如何使用name
元素,但是以下调整后的代码段将向您展示如何通过引用修改数组(注意&
的两种用法)。
代码:(Demo)
function recurseAll(&$node, $key) {
if (is_iterable($node)) {
foreach ($node as $key => &$childNode) {
recurseAll($childNode, $key);
}
} elseif ($key === "name") {
$node = "***{$node}***";
}
}
array_walk($array, 'recurseAll'); // or just call : recurseAll($array, null);
echo "After modified by reference:\n";
var_export($array);
输出:
After modified by reference:
array (
0 =>
array (
'name' => '***a***',
'url' => 'b',
),
1 =>
array (
'name' => '***c***',
'url' => 'd',
'children' =>
array (
0 =>
array (
'name' => '***e***',
'url' => 'f',
),
),
),
)