PHP.mk документација

array_walk_recursive

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

function.array-walk-recursive.php PHP.net прокси Преводот е вчитан
Оригинал на PHP.net
Патека function.array-walk-recursive.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + преведен приказ Кодовите, табелите и белешките остануваат читливи во истиот тек.
array_walk_recursive

Референца за `function.array-walk-recursive.php` со подобрена типографија и навигација.

function.array-walk-recursive.php

array_walk_recursive

класата mysqli_driver

array_walk_recursiveПримени корисничка функција рекурзивно на секој член од низата

= NULL

array_walk_recursive(array|object &$array, callable $callback, mixed $arg = null): true

Примени корисничка функција на секој член од низата callback Ги применува кориснички дефинираните array. Оваа функција ќе рекурзира во подлабоки низи.

Параметри

array

Влезната низа.

callback

ќе помине низ целата низа без оглед на позицијата на покажувачот. callback Типично, array зема два параметри. Вредноста на

Забелешка:

Враќа callback параметарот е првиот, а клучот/индексот вториот. callback како referenceтреба да работи со вистинските вредности на низата, специфицирајте го првиот параметар на

arg

Ако опционалниот arg ; неговата структура не може да се промени, т.е. програмерот не може да додава, откажува или преуредува елементи. Ако повикот не го почитува овој услов, однесувањето на оваа функција е недефинирано и непредвидливо. callback.

Вратени вредности

Секогаш враќа true.

Дневник на промени

Верзија = NULL
8.2.0 Типот на враќање е true сега; претходно, беше bool.

Примери

Пример #1 array_walk_recursive() example

<?php
$sweet
= array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => 'lemon');

function
test_print($item, $key)
{
echo
"$key holds $item\n";
}

array_walk_recursive($fruits, 'test_print');
?>

Пример #1 Пример што покажува затворачка ознака што го опфаќа последниот нов ред

a holds apple
b holds banana
sour holds lemon

Можеби ќе забележите дека клучот 'sweet' никогаш не се прикажува. Секој клуч што држи array нема да биде предаден на функцијата.

Види Исто така

  • array_walk() - Применете корисничка функција на секој член од низа

Белешки од корисници фајлови со горенаведените екстензии. Иако е форма на безбедност преку замаглување, тоа е мала превентивна мерка со малку недостатоци.

ниту еден на точката вашата точка биз
12 години пред
Since this is only mentioned in the footnote of the output of one of the examples, I feel it should be spelled out:

* THIS FUNCTION ONLY VISITS LEAF NODES *

That is to say that if you have a tree of arrays with subarrays of subarrays, only the plain values at the leaves of the tree will be visited by the callback function.  The callback function isn't ever called for a nodes in the tree that subnodes (i.e., a subarray).  This has the effect as to make this function unusable for most practical situations.
ghoffman на salientdigital точка com
пред 14 години
If you are wanting to change the values of an existing multi-dimensional array, as it says above in the note, you need to specify the first argument as a reference. All that means is, be sure to precede the $item variable with an ampersand (&) as in the good_example below. 

Unfortunately the PHP example given doesn't do this. It actually took me a while to figure out why my function wasn't changing the original array, even though I was passing by reference. 

Here's the tip: Don't return any value from the function! Just change the value of $item that you passed in by reference. This is rather counter-intuitive since the vast majority of functions return a value.

<?php
// array_walk_recursive fails to change your array unless you pass by reference.
// Don't return values from your filter function, even though it's quite logical at a glance!
function bad_example($item,$key){
   if($key=='test'){
       return 'PHP Rocks';  // Don't do it
   }else{
      return $item;  // Don't do this either
   }
}

// array_walk_recursive pass-by-reference example
function good_example(&$item,$key){
   if($key=='test'){
        $item='PHP Rocks'; // Do This!
   }
}

$arr = array('a'=>'1','b'=>'2','test'=>'Replace This');

array_walk_recursive($arr,'bad_example');
var_dump($arr);
/**
 * no errors, but prints...
 * array('a'=>'1','b'=>'2','test'=>'Replace This');
 */

array_walk_recursive($arr,'good_example');
var_dump($arr);
/**
 * prints...
 * array('a'=>'1','b'=>'2','test'=>'PHP Rocks');
 */

?>

Returning a value from your function does work if you pass by reference and modify $item before you return, but you will eat up memory very, very fast if you try it, even on an example as small as the one here.

One other silly thing you might try first is something like this:

<?php
// Resist the urge to do this, it doesn't work.
$filtered = array_walk_recursive($unfiltered,'filter_function');
?>

Of course, $filtered is just TRUE afterwards, not the filtered results you were wanting. Oh, it ran your function recursively alright, but changed all the values in the local function scope only and returns a boolean as the documentation states.
r
пред 7 години
How to modify external variable from inside recursive function using userdata argument.

<?php
$arr = [
   'one' => ['one_one' => 11, 'one_two' => 12],
   'two' => 2
];

$counter = 0;

//Does not persist
array_walk_recursive( $arr, function($value, $key, $counter) {
   $counter++;
   echo "$value : $counter";  
}, $counter);
echo "counter : $counter"; 

// result
// 11 : 1
// 12 : 1
// 2 : 1
// counter: 0 

//Persists only in same array node
array_walk_recursive( $arr, function($value, $key, &$counter) {
   $counter++;
   echo "$value : $counter";  
}, $counter);

// result
// 11 : 1
// 12 : 2
// 2 : 1
// counter : 0

//Fully persistent. Using 'use' keyword
array_walk_recursive( $arr, function($value, $key) use (&$counter) {
   $counter++;
   echo "$value : $counter";  
}, $counter);
echo "counter : $counter"; 

// result
// 11 : 1
// 12 : 2
// 2 : 3
// counter : 3
мајк на mpsharp точка com
пред 6 години
Here's a more general solution to modifying the array to which the leaf belongs.   You can unset the current key, or add siblings, etc.

<?php
/**
 * 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);
        }
    }
}
?>
php на genjo точка fr
пред 11 години
I use RecursiveIteratorIterator with parameter CATCH_GET_CHILD to iterate on leafs AND nodes instead of array_walk_recursive function :

<?php
// Iteration on leafs AND nodes
foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($candidate), RecursiveIteratorIterator::CATCH_GET_CHILD) as $key => $value) {
    echo 'My node ' . $key . ' with value ' . $value . PHP_EOL;
}
?>
CommentUser
пред 8 години
The following code, which returns back a flattened array of sorts into the $results array, in newer versions of PHP raises the error "PHP Fatal error:  Call-time pass-by-reference has been removed":

<?php 

$results = array();

function example_function ($item, $key, &$arr_values)
{
    $arr_values[$key] = $item; 
}

array_walk_recursive($data, 'example_function', &$results);

print_r($results);

?>

This can be fixed using an anonymous function:

<?php

$results = array();

array_walk_recursive($data, function ($item, $key) use (&$results){$results[$key] = $item;});

print_r($results);

?>
gk на anuary dot com
12 години пред
array_walk_recursive itself cannot unset values. Even though you can pass array by reference, unsetting the value in the callback will only unset the variable in that scope.

<?php
/**
 * 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;
}
?>

An up to date implementation of the above function can be looked up from https://github.com/gajus/marray/blob/master/src/marray.php#L116.
bradbeattie на gmail точка com
пред 15 години
The description says "If funcname needs to be working with the actual values of the array, specify the first parameter of funcname as a reference." This isn't necessarily helpful as the function you're calling might be built in (e.g. trim or strip_tags). One option would be to create a version of these like so.

<?php
    function trim_by_reference(&$string) {
        $string = trim($string);
    }
?>

The downside to this approach is that you need to create a wrapper function for each function you might want to call. Instead, we can use PHP 5.3's inline function syntax to create a new version of array_walk_recursive.

<?php
    /**
     * This function acts exactly like array_walk_recursive, except that it pretends that the function
     * its calling replaces the value with its result.
     * 
     * @param $array The first value of the array will be passed into $function as the primary argument
     * @param $function The function to be called on each element in the array, recursively
     * @param $parameters An optional array of the additional parameters to be appeneded to the function
     * 
     * Example usage to alter $array to get the second, third and fourth character from each value
     *     array_walk_recursive_referential($array, "substr", array("1","3"));
     */
    function array_walk_recursive_referential(&$array, $function, $parameters = array()) {
        $reference_function = function(&$value, $key, $userdata) {
            $parameters = array_merge(array($value), $userdata[1]);
            $value = call_user_func_array($userdata[0], $parameters);
        };
        array_walk_recursive($array, $reference_function, array($function, $parameters));
    }
?>

The advantage here is that we only explicitly define one wrapper function instead of potentially dozens.
Дарио
пред 7 години
I was looking for how to change values of array since you can't pass array by reference anymore in new PHP versions, here is simple solution

<?php
array_walk_recursive(
    $myArray,
    function (&$value) {
        if (/*some condition*/) {
            $value = 'New value';
        }
    }
);
?>

After that $myArray will be altered with new value.
cyranix на cyranix точка com
пред 14 години
I needed to add or modify values in an array with unknown structure. I was hoping to use array_walk_recursive for the task, but because I was also adding new nodes I came up with an alternate solution.

<?php

    /**
     * Sets key/value pairs at any depth on an array.
     * @param $data an array of key/value pairs to be added/modified
     * @param $array the array to operate on
     */
    function setNodes($data, &$array)
    {
        $separator = '.'; // set this to any string that won't occur in your keys
        foreach ($data as $name => $value) {
            if (strpos($name, $separator) === false) {
                // If the array doesn't contain a special separator character, just set the key/value pair. 
                // If $value is an array, you will of course set nested key/value pairs just fine.
                $array[$name] = $value;
            } else {
                // In this case we're trying to target a specific nested node without overwriting any other siblings/ancestors. 
                // The node or its ancestors may not exist yet.
                $keys = explode($separator, $name);
                // Set the root of the tree.
                $opt_tree =& $array;
                // Start traversing the tree using the specified keys.
                while ($key = array_shift($keys)) {
                    // If there are more keys after the current one...
                    if ($keys) {
                        if (!isset($opt_tree[$key]) || !is_array($opt_tree[$key])) {
                            // Create this node if it doesn't already exist.
                            $opt_tree[$key] = array();
                        }
                        // Redefine the "root" of the tree to this node (assign by reference) then process the next key.
                        $opt_tree =& $opt_tree[$key];
                    } else {
                        // This is the last key to check, so assign the value.
                        $opt_tree[$key] = $value;
                    }
                }
            }
        }
    }

?>

Sample usage: 

<?php

$x = array();
setNodes(array('foo' => 'bar', 'baz' => array('quux' => 42, 'hup' => 101)), $x);
print_r($x); // $x has the same structure as the first argument
setNodes(array('jif.snee' => 'hello world', 'baz.quux.wek' => 5), $x);
print_r($x); // added $x['jif']['snee'] and modified $x['baz']['quux'] to be array('wek' => 5)

?>
amoffat на amoffat точка com
пред 17 години
<?
function my_array_map() {
    $args = func_get_args();
    $arr = array_shift($args);
    
    foreach ($args as $fn) {
        $nfn = create_function('&$v, $k, $fn', '$v = $fn($v);');
        array_walk_recursive($arr, $nfn, $fn);
    }
    return $arr;
}
?>

takes an array as the first argument, and functions as the other arguments.  it applies those functions recursively to the array
робин лефман
пред 11 години
A simple solution for walking a nested array to obtain the last set value of a specified key:

<?php

$key = 'blah';
$val = null;
array_walk_recursive( $your_array,
                      function($v, $k, $u) { if($k === $u[0]) $u[1] = $v; },
                      [$key ,&$val] );

echo "$key = $val";

?>
gabrielu на hotmail точка com
20 години пред
I decided to add to the previous PHP 4 compatible version of array_walk_recursive() so that it would work within a class and as a standalone function.  Both instances are handled by the following function which I modified from omega13a at sbcglobal dot net.

The following example is for usage within a class.  To use as a standalone function take it out of the class and rename it.  (Example: array_walk_recursive_2)

<?php
class A_Class {

function array_walk_recursive(&$input, $funcname, $userdata = '') {
  if(!function_exists('array_walk_recursive')) {
    if(!is_callable($funcname))
      return false;

    if(!is_array($input))
      return false;

    foreach($input as $key=>$value) {
      if(is_array($input[$key])) {
        if(isset($this)) {
          eval('$this->' . __FUNCTION__ . '($input[$key], $funcname, $userdata);');
        } else {
          if(@get_class($this))
            eval(get_class() . '::' . __FUNCTION__ . '($input[$key], $funcname, $userdata);');
          else
            eval(__FUNCTION__ . '($input[$key], $funcname, $userdata);');
        }
      } else {
        $saved_value = $value;

        if(is_array($funcname)) {
          $f = '';
          for($a=0; $a<count($funcname); $a++)
            if(is_object($funcname[$a])) {
              $f .= get_class($funcname[$a]);
            } else {
              if($a > 0)
                $f .= '::';
              $f .= $funcname[$a];
            }
          $f .= '($value, $key' . (!empty($userdata) ? ', $userdata' : '') . ');';
          eval($f);
        } else {
          if(!empty($userdata))
            $funcname($value, $key, $userdata);
          else
            $funcname($value, $key);
        }

        if($value != $saved_value)
          $input[$key] = $value;
      }
    }
    return true;
  } else {
    array_walk_recursive($input, $funcname, $userdata);
  }
}

function kv_addslashes(&$v, $k) {
  $v = addslashes($v);
}
}
?>

Usage:
<?php
$arr = array(
  'a' => '"Hello World"',
  'b' => "'Hello World'",
  'c' => "Hello 'Worl\"d",
  'd' => array(
    'A' => 'H"e"l"l"o" "W"o"r"l"d'
    )
  );

$class = new A_Class();
$class->array_walk_recursive($arr, array(&$class, 'kv_addslashes'));
print_r($arr);
?>
Анонимен
12 години пред
since PHP 5.3.0, you will get a warning saying that "call-time pass-by-reference" is deprecated when you use & in foo(&$a);. And as of PHP 5.4.0, call-time pass-by-reference was removed, so using it will raise a fatal error.
Premysl Karbula
пред 8 години
multidimensional array to single array 

$array=[1=>[2,5=>[4,2],[7,8=>[3,6]],5],4];
$arr=[];
array_walk_recursive($array, function($k){global $arr; $arr[]=$k;});
print_r($arr);

Output

Array ( [0] => 2 [1] => 4 [2] => 2 [3] => 7 [4] => 3 [5] => 6 [6] => 5 [7] => 4 )
4 месеци пред
пред 1 година
If you want to iterate both arrays and objects interchangeably:
<?php
function array_and_object_walk_recursive(array|object &$array, callable $callback, mixed $arg = null): true
{
    $argumentCount = func_num_args();
    if ($argumentCount > 3) {
        throw new \ArgumentCountError("array_and_object_walk_recursive() expects at most 3 arguments, $argumentCount given");
    }
    $hasThirdArgument = ($argumentCount === 3);
    foreach ($array as $key => &$value) {
        if (is_array($value) || is_object($value)) {
            if ($hasThirdArgument) {
                array_and_object_walk_recursive($value, $callback, $arg);
            } else {
                array_and_object_walk_recursive($value, $callback);
            }
        }
        if ($hasThirdArgument) {
            ($callback)($value, $key, $arg);
        } else {
            ($callback)($value, $key);
        }
    }
    return true; // just mimicking array_walk_recursive
}

?>
Useful if you have large array-and-object soup in production code.
Premysl Karbula
пред 5 години
Normal function solution

//1,2,2,3,6,7,3,1,4,2
$arr=[
    [1,2],
    [2,3],
    6,7,[3,1,[4,2]]
];

function a($array){
    static $res=[];
    foreach($array as $val){
        if(is_array($val)){
            a($val);
        }else{
            $res[]=$val;
        }
    }
    return $res;
}

print_r(a($arr));
Анонимен
пред 8 години
multidimensional array to single array 

$array=[1=>[2,5=>[4,2],[7,8=>[3,6]],5],4];
$arr=[];
array_walk_recursive($array, function($k){global $arr; $arr[]=$k;});
print_r($arr);

Output

Array ( [0] => 2 [1] => 4 [2] => 2 [3] => 7 [4] => 3 [5] => 6 [6] => 5 [7] => 4 )
Родриго Гуариенто
12 години пред
Simple array_walk_recursive:

// var example
$myArray = Array(
  Array('keyA1' => '    textA1 ', 'keyA2' => '  textA2     '),
  Array('keyB1' => '    textB1 ', 'sub' => 
        Array('keyB1_sub1' => '      textB1_sub1   '),
          Array('keyB1_sub2' => '      textB1_sub2   ')
      ),
  Array('keyC1' => '    textC1 ', 'keyC2' => '  textC2     '),
  Array('keyD1' => '    textD1 ', 'keyD2' => '  textD2     '),
  Array('keyE1' => '    textE1 ', 'keyE2' => '  textE2     ')
);

// function for "trim" (or your function, use same structure)
function trimming($data) {
  if (gettype($data) == 'array')
    return array_map("trimming", $data);
  else
    return trim($data);
}

// get array
$myArray = array_map("trimming", $myArray);

// show array trimmed
var_dump($myArray);

/*
RESULT

array (size=5)
  0 => 
    array (size=2)
      'keyA1' => string 'textA1' (length=6)
      'keyA2' => string 'textA2' (length=6)
  1 => 
    array (size=3)
      'keyB1' => string 'textB1' (length=6)
      'sub' => 
        array (size=1)
          'keyB1_sub1' => string 'textB1_sub1' (length=11)
      0 => 
        array (size=1)
          'keyB1_sub2' => string 'textB1_sub2' (length=11)
  2 => 
    array (size=2)
      'keyC1' => string 'textC1' (length=6)
      'keyC2' => string 'textC2' (length=6)
  3 => 
    array (size=2)
      'keyD1' => string 'textD1' (length=6)
      'keyD2' => string 'textD2' (length=6)
  4 => 
    array (size=2)
      'keyE1' => string 'textE1' (length=6)
      'keyE2' => string 'textE2' (length=6)

*/
крис на willowsconsulting точка ie
пред 13 години
To convert all values of an array in UTF8, do this:

<?php

function convert_before_json(&$item, &$key)
{
   $item=utf8_encode($item);
}

array_walk_recursive($your_array,"convert_before_json");

?>
JW
пред 18 години
This function has a serious bug, which is still not fixed as of the PHP 5.2.5 release. After you call it, it can accidentally modify your original array. Save yourself hours of frustration by reading on.

The bug is here: http://bugs.php.net/bug.php?id=42850, and it looks like it will be fixed for 5.3.

If the array that you walk contains other array elements, they will be turned into references. This will happen even if the callback function doesn't take its first argument by reference, and doesn't do anything to the values.

For example, try this:
<?php
$data = array ('key1' => 'val1', 'key2' => array('key3' => 'val3'));
function foo($item, $key){}
var_dump($data);
?>

The original array has no references. Now try this:
<?php
array_walk_recursive($data,'foo');
var_dump($data);
?>

Now key2 is a reference, not just an array. So if you do this:
<?php
function test($item){$item['key2'] = array();}
test($data);
var_dump($data);
?>

you will see that test modifies $data, even though it shouldn't.

One workaround is to immediately make a deep copy of the array after calling array_walk_recursive, like this:
<?php
function array_duplicate($input) {
  if (!is_array($input)) return $input;
  $output = array();
  foreach ($input as $key => $value) {
    $output[$key] = array_duplicate($value);
  }
  return $output;
}
array_walk_recursive($data,'foo');
$data = array_duplicate($data);
var_dump($data);
?>

After doing that, the references are gone.
seductiveapps.com
пред 8 години
usage :
$nd = $newsApp2->dataSources();
//walkArray ($nd, 'walkArray_printKey', 'walkArray_printValue');
// prints the entire array

$x = chaseToPath ($nd, 'RSS_list/English News',false);
walkArray ($x, 'walkArray_printKey', 'walkArray_printValue');
// prints everything under $nd['RSS_list']['English News']

function &chaseToPath (&$wm, $path, $create=false) {
    //var_dump ($create); die();
    //echo '$wm=<pre>'; var_dump ($wm);echo '</pre>'; //die();
    //$path = str_replace ('/', '/d/', $path);
    //$path .= '/d';
    $nodes = explode ('/', $path);
    $chase = &chase ($wm, $nodes, $create);
    
    //echo '$wm=<pre>'; var_dump ($wm);echo '</pre>'; die();
    /*
    $dbg = array (
        '$path' => $path,
        '$nodes' => $nodes,
        '$wm' => $wm,
        '$chase' => $chase
    );
    echo '$dbg=<pre style="background:red;color:yellow;">'; var_dump ($dbg); echo '</pre>';
    */
    //die();
    
    
    $false = false;
    if (good($chase)) {
        $arr = &result($chase);    
        return $arr;
    } else return $false;
}        

function &chase (&$arr, $indexes, $create=false) {
        if (false) {
        echo 'sitewide/functions.php --- $arr=<pre>'; var_dump ($arr); echo '</pre>';
        echo 'sitewide/functions.php --- $indexes=<pre>'; var_dump ($indexes); echo '</pre>';
        echo 'sitewide/functions.php --- $create=<pre>'; var_dump ($create); echo '</pre>';
        }
    $r = &$arr;
    foreach ($indexes as $idx) {
            //echo 'sitewide/functions.php --- $idx=<pre>'; var_dump ($idx); var_dump (array_key_exists($idx,$r)); var_dump ($r); echo '</pre>';
            if (
                    is_array($r)
                    && (
                            $create===true 
                            || array_key_exists($idx,$r)
                    )
            ) {
                    if ($create===true && !array_key_exists($idx,$r)) $r[$idx]=array();
                    //echo 'sitewide/functions.php --- $idx=<pre>'; var_dump ($idx); echo '</pre>';
                    $r = &$r[$idx];
            } else {
                    $err = array(
                    'msg' => 'Could not walk the full tree',
                    'vars' => array(
                            '$idx--error'=>$idx,
                            '$indexes'=>$indexes,
                            '$arr'=>$arr
                            )
                    );
                    badResult (E_USER_NOTICE, $err);
                    $ret = false; // BUG #2 squashed
                    return $ret;
            }
    }
    
        //echo 'sitewide/functions.php --- $r=<pre>'; var_dump ($r); echo '</pre>';
    return goodResult($r);
}
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.