如何使用array_walk_recursive取消设置元素

时间:2011-06-04 09:25:59

标签: php arrays recursion multidimensional-array

我需要从嵌套到另一个数组的数组中取消设置元素,其方式是只保留第一个N元素(预定义N)。只有具有数字索引的元素才会受到影响。

输入数组:

Array
(
    [0] => Array (
        [a] => 'w'
        [b] => Array (
             [0]=> 'x'
             [1]=> 'x'
             [2]=> 'x'
        )
    )               
    [1] => Array (
        [a] => 'y'
    )
    [2] => Array (
        [0] => 'z'
        [1] => 'z'
        [2] => 'z'
    )
)

所需的输出(N=2):

Array
(
    [0] => Array (
        [a] => 'w'
        [b] => Array (
             [0]=> 'x'
             [1]=> 'x'
        )
    )               
    [1] => Array (
        [a] => 'y'
    )
)

根据上面的定义,只有[0][b][2][2]未设置,因为它们有一个数字索引,因为它们都重写了各自数组的第3个元素。

5 个答案:

答案 0 :(得分:5)

没有经过测试,但这样的事情可能有用。

function myFunc(&$array){
foreach($array as $key=>&$value){
 if(is_array($value)){
   myFunc($value);
 }
 if(is_numeric($key) && $key > 1){
   unset($array[$key]);
 }
}
}

关于array_walk。 php.net说:

  

程序员无法添加,取消设置或   重新排序元素。如果回调了   不尊重这个要求,   这个功能的行为是   未定义,不可预测。

答案 1 :(得分:1)

给自己写一个完全符合你想要的功能。然后记录该函数,如果您需要在大约两周内使用它,您可能想知道该函数到底在做什么。

我这样说是因为您想要处理的数据结构似乎非常具体。所以值得将它封装在一个函数中,以隐藏复杂性。正确命名函数。

在函数内部,您可以以各种方式处理数据,并具备您需要制定的各种条件。来自外部的参数可以作为函数参数传递。返回值是您希望实现的结果。

答案 2 :(得分:1)

这对我有用,也许不是最干净的代码。

$array = array
(
    array(
        'a' => 'w',
        'b' => array('x','x','x')
    ),
    array(
        'a' => 'y'
    ),
    array(
        'z','z','z'
    )
);

function recurse_and_strip ($array, &$size=2)
{
    foreach ($array as $key => &$element)
    {
        if (is_hash($element))
        {
            $element = recurse_and_strip($element,$size);
        } else if (is_array($element))
        {
            $deletefrom = false;
            // now the tricky part.. see how many must be deleted
            for ($i=0; $i < count($element); $i++ )
            {
                if ($size == 0)
                {
                    echo "Delete from " . $i;
                    $deletefrom = $i;
                    break 1;
                }
                $size--;
            }
            if ($deletefrom !== false)
            {
                if ($deletefrom == 0)
                {
                    unset($array[$key]);
                } else {
                    array_splice($element,$deletefrom);
                }
            }
        }
    }
    return $array;
}

// source http://www.benjaminkeen.com/?p=23
function is_hash($var)
{
  if (!is_array($var))
    return false;

  return array_keys($var) !== range(0,sizeof($var)-1);
}

var_dump(recurse_and_strip($array,2));

答案 3 :(得分:1)

array_walk_recursive本身无法达到你想要的效果。即使你可以通过引用传递数组,在回调中取消设置变量只会在该范围内取消设置。

但是,您可以使用walk_recursive_remove功能:

/**
 * http://uk1.php.net/array_walk_recursive implementation that is used to remove nodes from the array.
 *
 * @param array The input array.
 * @param callable $callback Function must return boolean value indicating whether to remove the node.
 * @return array
 */
function walk_recursive_remove (array $array, callable $callback) {
    foreach ($array as $k => $v) {
        if (is_array($v)) {
            $array[$k] = walk_recursive_remove($v, $callback);
        } else {
            if ($callback($v, $k)) {
                unset($array[$k]);
            }
        }
    }

    return $array;
}

您需要使用$callback实现自己的逻辑以取消设置特定值。

答案 4 :(得分:0)

这是修改叶子所属数组的更通用的解决方案。您可以取消设置当前密钥,或添加同级兄弟等。

/**
 * Modified version of array_walk_recursive that passes in the array to the callback
 * The callback can modify the array or value by specifying a reference for the parameter.
 *
 * @param array The input array.
 * @param callable $callback($value, $key, $array)
 */
function array_walk_recursive_array(array &$array, callable $callback) {
    foreach ($array as $k => &$v) {
        if (is_array($v)) {
            array_walk_recursive_array($v, $callback);
        } else {
            $callback($v, $k, $array);
        }
    }
}