array_map

(PHP 4 >= 4.0.6, PHP 5)

array_map --  Применить функцию обратного вызова ко всем элементам указанных массивов

Описание

array array_map ( mixed callback, array array1 [, array array2...] )

Функция array_map() возвращает массив, содержащий элементы всех указанных массивов после их обработки функцией обратного вызова. Количество параметров, передаваемых функции обратного вызова, должно совпадать с количеством массивов, переданным функции array_map().

Пример 1. Пример использования array_map()

function cube($n) {
   return $n*$n*$n;
}

$a = array(1, 2, 3, 4, 5);
$b = array_map("cube", $a);
print_r($b);

В результате переменная $b будет содержать:
Array
(
    [0] => 1
    [1] => 8
    [2] => 27
    [3] => 64
    [4] => 125
)

Пример 2. Пример использования array_map(): обработка нескольких массивов

function show_Spanish($n, $m) {
   return "Число $n по-испански -  $m";
}

function map_Spanish($n, $m) {
   return array ($n => $m);
}

$a = array(1, 2, 3, 4, 5);
$b = array("uno", "dos", "tres", "cuatro", "cinco");

$c = array_map("show_Spanish", $a, $b);
print_r($c);

$d = array_map("map_Spanish", $a , $b);
print_r($d);

Результат выполнения:
// printout of $c
Array
(
    [0] => Число 1 по-испански -  uno
    [1] => Число 2 по-испански -  dos
    [2] => Число 3 по-испански -  tres
    [3] => Число 4 по-испански -  cuatro
    [4] => Число 5 по-испански -  cinco
)

// printout of $d
Array
(
    [0] => Array
        (
            [1] => uno
        )

    [1] => Array
        (
            [2] => dos
        )

    [2] => Array
        (
            [3] => tres
        )

    [3] => Array
        (
            [4] => cuatro
        )

    [4] => Array
        (
            [5] => cinco
        )

)

Обычно при обработке двух или более массивов, они имею одинаковую длину, так как функция обратного вызова применяется параллельно к соответствующим элементам массивов. Если массивы имеют различную длину, самый маленький из них дополняется элементами с пустыми значениями.

Интересным эффектом при использовании этой функции является создание массива массивов, что может быть достигнуто путем использования значения NULL в качестве имени функции обратного вызова.

Пример 3. Создание массива массивов

$a = array(1, 2, 3, 4, 5);
$b = array("one", "two", "three", "four", "five");
$c = array("uno", "dos", "tres", "cuatro", "cinco");

$d = array_map(null, $a, $b, $c);
print_r($d);

Результатом выполнения вышеприведенной программы будет:
Array
(
    [0] => Array
        (
            [0] => 1
            [1] => one
            [2] => uno
        )

    [1] => Array
        (
            [0] => 2
            [1] => two
            [2] => dos
        )

    [2] => Array
        (
            [0] => 3
            [1] => three
            [2] => tres
        )

    [3] => Array
        (
            [0] => 4
            [1] => four
            [2] => cuatro
        )

    [4] => Array
        (
            [0] => 5
            [1] => five
            [2] => cinco
        )

)

См.также array_filter() и array_reduce().



array_map
pcdinh at phpvietnam dot net
17-Mar-2006 08:50
Hi benjaminhill,

You can apply a method of a instantiated class to array_maps as follows:

class Maths {
   function addOne($input) {
       return ($input + 1);
   }
}
$maths = new Maths();
$sum = array_map(array($maths, \\\'addOne\\\'), array(1, 2));
// where $maths is the object which has been instantiated before and addOne is its method without its own parameters
var_dump($sum);

The code fragment will return:

array
  0 => 2
  1 => 3

However, I love a syntax like this:

$sum = array_map($maths->addOne($this), array(1, 2));

where $this should be interpreted as each values extracted from the subsequent array, which in this case is array(1, 2).

This syntax reminds me of Javascript syntax.

PHP\\\'s callback mechanism should be improved.
jakob dot buchgraber at gmail dot com
17-Dec-2005 10:41
This function escapes an array or string. The function uses addslashes for escaping the data, but if you work with i.e. MySQL you should use mysqli_real_escape_string() instead.

<?php
function escapeString($stringOrArray) {

  if (
is_array($stringOrArray))
   return
array_map('escapeString',$stringOrArray);
  else {
  
$stringOrArray = addslashes($stringOrArray);
   return
$stringOrArray;
  }
}

$array  = array('"""\\\$',"Peter's here");
$string = 'Hello I am "Mr XYZ"';

$array = escapeString($array);
$string = escapeString($string);

echo
'<pre>';
print_r($array);
echo
'</pre>';

echo
$string;

/************The Output*******************
Array
(
   [0] => \"\"\"\\\\$
   [1] => Peter\'s here
)

Hello I am \"Mr XYZ\"
*************The Output******************/
?>
26-Aug-2005 06:57
Here's a function, very helpfull to me, that allows you to map your callback on mixed args.

<?php
function array_smart_map($callback) {
  
// Initialization
  
$args = func_get_args() ;
  
array_shift($args) ; // suppressing the callback
  
$result = array() ;
  
  
// Validating parameters
  
foreach($args as $key => $arg)
       if(
is_array($arg)) {
          
// the first array found gives the size of mapping and the keys that will be used for the resulting array
          
if(!isset($size)) {
              
$keys = array_keys($arg) ;
              
$size = count($arg) ;
          
// the others arrays must have the same dimension
          
} elseif(count($arg) != $size) {
               return
FALSE ;
           }
          
// all keys are suppressed
          
$args[$key] = array_values($arg) ;
       }
  
  
// doing the callback thing
  
if(!isset($size))
      
// if no arrays were found, returns the result of the callback in an array
      
$result[] = call_user_func_array($callback, $args) ;
   else
       for(
$i=0; $i<$size; $i++) {
          
$column = array() ;
           foreach(
$args as $arg)
              
$column[] = ( is_array($arg) ? $arg[$i] : $arg ) ;
          
$result[$keys[$i]] = call_user_func_array($callback, $column) ;
       }
          
   return
$result ;
  
}
?>

Trying with :

<?php
// $_GET is ?foo=bar1-bar2-bar3&bar=foo1
print_r(array_smart_map('explode', '-', $_GET)) ;
?>

Returns :

array(
   [foo] => array(
       0 => bar1
       1 => bar2
       2 => bar3
   )

   [bar] => array(
       1 => foo1
   )
)
david dot tulloh at infaze dot com dot au
06-Jul-2005 04:53
You can pass values to array_map by reference, essentially allowing you to use it as you would array_walk with multiple arrays as parameters.

A trivial example:
<?php
$a
= array(1,2,3,4,5);
$add_func = create_function('&$x, $y', '$x+=$y;');
array_map($add_func, $a, $a);
print_r($a);
?>
Array
(
   [0] => 2
   [1] => 4
   [2] => 6
   [3] => 8
   [4] => 10
)
arunas Baltuonis
02-Jul-2005 02:57
In PHP5 array_map doesn't check "arrays in arrays". Here is simple example how to clean deep all array.

function clean ( $string )
{
   if (is_array($string))
   {
       return array_map('clean', $string);; 
   }
   return ereg_replace("[^[:space:]a-zA-Z0-9*_.-\]\[]", " ", $string);

}

$_GET = array_map('clean', $_GET);
$_POST = array_map('clean', $_POST);
ildar-sh [at] mail [dot] ru
24-May-2005 11:45
I think that thise code can be useful for an string<->assoc.array convertation
<?php

/*
// Example:
$origin = array('a' => 1, 'b' => 2, 'c' => 3);
$joined = PrepareRequest::join($origin);
$splitted = PrepareRequest::split($joined);
print_r(array('origin' => $origin, 'joined' => $joined, 'splitted' => $splitted));
*/

class PrepareRequest
{

      
/*
       * string PrepareRequest::join(array $array [ , char $delim1 [ , char $delim2 ] ] )
       *
       * Converting of arrays to the strings. Resulting string contains keys and values
       * correctly for HTTP requests such as key1=value1&key2=value2...
       *
       */
  
function join($array, $delim1='&', $delim2='=')
   {
      
array_walk($array, array('PrepareRequest', '_join'), $delim2);
       return
implode($delim1, $array);
   }

   function
_join(&$value, $key, $delim2)
   {
      
$value = $key . $delim2 . $value;
   }

  
/*
   * array PrepareRequest::split(string $string [ , char $delim1 [ , char $delim2 ] ] )
   *
   * Parsing of string to associative array
   */
  
function split($string, $delim1='&', $delim2='=')
   {
      
$array = explode($delim1, $string);
      
$result = array();
       for (
$i = 0; $i < count($array); $i++)
       {
               list(
$key, $value) = explode($delim2, $array[$i], 2);
          
$result[$key] = $value;
       }
       return
$result;
   }

}

?>
Vinicius Cubas Brand
23-Mar-2005 05:31
The following function does exaclty the same thing of array_map. However, maintains the same index of the input arrays

<?php
  
function array_map_keys($param1,$param2,$param3=NULL)
   {
      
$res = array();

       if (
$param3 !== NULL)
       {
           foreach(array(
2,3) as $p_name)
           {
               if (!
is_array(${'param'.$p_name}))
               {
                  
trigger_error(__FUNCTION__.'(): Argument #'.$p_name.' should be an array',E_USER_WARNING);
                   return;
               }
           }
           foreach(
$param2 as $key => $val)
           {
              
$res[$key] = call_user_func($param1,$param2[$key],$param3[$key]);
           }
       }
       else
       {
           if (!
is_array($param2))
           {
              
trigger_error(__FUNCTION__.'(): Argument #2 should be an array',E_USER_WARNING);
               return;
           }
           foreach(
$param2 as $key => $val)
           {
              
$res[$key] = call_user_func($param1,$param2[$key]);
           }
       }
       return
$res;
   }
?>

For instance:

<?php
   $arr1
= array(
      
'3' => 'a',
      
'4' => 'b',
      
'5' => 'c'
      
);

  
$arr2 = array(
      
'3' => 'd',
      
'4' => 'e',
      
'5' => 'f'
      
);

  
$arr3 = array_map_keys(create_function('$a,$b','return $a.$b;'),$arr1,$arr2);

  
print_r($arr3);

?>

The result will be:

Array
(
   [3] => ad
   [4] => be
   [5] => cf
)
nick at netdupeNOSPAM dot com
21-Feb-2005 09:34
This function comes in handy for $_POST, $_GET input. Allowing you to quickly check user input.

For example:

<?php

$_POST
= array_map('addslashes', $_POST);

//or

$_GET = array_map('addslashes', $_GET);

?>

You could also use it to trim, strip tags etc. Saves a lot of time when having to check a lot of input values.
endofyourself at yahoo dot com
19-Feb-2005 11:29
If you need to call a static method from array_map, this will NOT work:

<?PHP
array_map
('myclass::myMethod' , $value);
?>

Instead, you need to do this:

<?PHP
array_map
( array('myclass','myMethod') , $value);
?>

It is helpful to remember that this will work with any PHP function which expects a callback argument.
Clayton Smith
29-Nov-2004 10:28
Handle multidimensional arrays:
function array_map_recursive($func, $arr)
{
   $result = array();
   do
   {
       $key = key($arr);
       if (is_array(current($arr))) {
           $result[$key] = array_map2($func, $arr[$key]);
       } else {
           $result[$key] = $func(current($arr));
       }     
   } while (next($arr) !== false);
   return $result;
}
19-Sep-2004 03:32
Note that you can also use PHP own functions:

$dir = glob("dir/*.txt");
$sizes = array_map("filesize", $dir);
print array_sum($sizes); // 157471

This script sums that folder txt-file sizes very well !
nd0 at gmx dot de
02-Jul-2004 04:42
array_map works also fine with create_function:

<?php
$a
= array(1, 2, 3, 4, 5);
$b = array_map(create_function('$n', 'return $n*$n*$n;'), $a);
print_r($b);
?>

if you want to manipulate the elements of the array, instead to on a copy,
than take a look at array_walk:

<?php
$a
= array(1, 2, 3, 4, 5);
array_walk($a, create_function('&$n', '$n = $n*$n*$n;'));
print_r($a);
?>

The Result of both is:

Array
(
   [0] => 1
   [1] => 8
   [2] => 27
   [3] => 64
   [4] => 125
)
nd0 at gmx.de
02-Jul-2004 04:07
Here's an other example, to handle array of arrays with array_map.
Only a small modification in the callback-function.

<?php
function cube($n) {
   if (
is_array($n)) return array_map('cube', $n);
   return
$n*$n*$n;
}

$a = array(1, 2, array(3, 4, array(5)));
$b = array_map('cube', $a);
print_r($b);
?>
bishop
09-Apr-2004 05:07
Occasionally, you may find that you need to pull out a column (or several) from an array.  Here's a map-like function to do that:

<?php
function &array_shear(&$arrays, $idx1 /* ... */) {
  
$indexes = func_get_args();
  
array_shift($indexes);

  
$newArrays = array ();

   foreach (
array_keys($arrays) as $arrayKey) {
      
$newArray = array ();
       foreach (
$indexes as $index) {
          
$newArray[$index] = $arrays[$arrayKey][$index];
           unset(
$arrays[$arrayKey][$index]);
       }
      
$newArrays[$arrayKey] = $newArray;
   }

   return
$newArrays;
}
?>

So, doing this:

<?php
$t1
= array (
        
2 => array ('a', 'b', 'c'),
        
1 => array ('d', 'e', 'f'),
        
5 => array ('g', 'h', 'i'),
     );

$t2 = array_shear($t1, 1, 0);

?>

will result in:

<?php

$t1
= array (
 
2 =>  array (    2 => 'c',  ),
 
1 =>  array (    2 => 'f',  ),
 
5 =>  array (    2 => 'i',  ),
);

$t2 = array (
 
2 =>  array (    1 => 'b',    0 => 'a',  ),
 
1 =>  array (    1 => 'e',    0 => 'd',  ),
 
5 =>  array (    1 => 'h',    0 => 'g',  ),
);

?>
stephen at mu dot com dot au
06-Jan-2003 10:02
A note when doing something allong the lines of:

<?php
class foo {
  var
$var;
  function
bar() {
    
array_map(array($this, "baz"), array(1,2,3));
  }

  function
baz($arg) {
  
$this->var = $this->var + $arg;
  }
}
?>

This will *not* work as expected. You need to pass $this by reference as with:

array_map(array(&$this, "baz"), array(1,2,3));

or you'll be making a copy of the object each time, changing a value, then throwing the result away.
NetVicious IN hotmail_com
23-Nov-2002 06:00
Get the max length in an array of strings

<?php
function maxLength($str) {
   return
strlen($str);
}

$maxLen = max(array_map("maxLength", $myArray));
?>
dan at mojavelinux dot com
14-Jun-2002 10:07
Here is a better, more true version of a deep array_map.  The only negative of this function is that the array is passed by reference, so just be aware of that. (patches welcome)

<?php
function array_map_deep(&$in_array, $in_func, $in_args = array(), $in_index = 1) {
  
// fix people from messing up the index of the value
  
if ($in_index < 1) {
      
$in_index = 1;
   }

   foreach (
array_keys($in_array) as $key) {
      
// we need a reference, not a copy, normal foreach won't do
      
$value =& $in_array[$key];
      
// we need to copy args because we are doing
       // manipulation on it farther down
      
$args = $in_args;
       if (
is_array($value)) {
          
array_map_deep($value, $in_func, $in_args, $in_index);
       }
       else {
          
array_splice($args, $in_index - 1, $in_index - 1, $value);
          
$value = call_user_func_array($in_func, $args);
       }
   }
  
   return
$in_array;
}
?>

This is a neat function because you can pass an array, a function, and an array of parameters, and finally, and index of where in the array of parameters for the callback function the contents you are mapping should get replaced.  This index is human based (starts at 1), and can be used in something like a preg_replace callback, where the contents must be the 3rd index.  Enjoy!
bishop
26-Mar-2002 03:33
Sometimes you might be interested in performing a "deep" map, where you apply the callback to all elements in the array, even if the elements are stuck deep inside of some array(array(array(...))) business.

Here's an example PHP4 function that handles this case, with a little bit more flexible (and potentially more error-prone) callback parameter:

<?php
function deepmap($cb, $x) {

   if (
is_array($x)) {
      
$it = array();
       foreach (
$x as $k => $v) {
          
$it["$k"] = deepmap($cb, $x["$k"]);
       }
       return
$it;
   } else {
      
$cmd = "return (" .
              
str_replace('$__', $x, $cb) .
              
");";
       return eval(
$cmd);
   }

}

So, you could do, for example:

$some_odds  = array(1, 3, 5);
$some_evens = array(0, 2, 4, 6);
$some_nums  = array($some_odds, array($some_evens));

deepmap('pow($__, 2)', $some_odds);
deepmap('pow($__, 2)', $some_nums);
?>

Both examples square each element of the arrays, making sure to keep the array structure intact.

Note that the callback function needs to be a) quoted, and b) include the special string $__ (dollar double underscore); deepmap replaces $__ in the function call with whatever the current element is.

<array_keysarray_merge_recursive>
 Last updated: Tue, 15 Nov 2005