ConFoo: Call for paper is now Open

array_map

(PHP 4 >= 4.0.6, PHP 5)

array_mapAplica la retrollamada especificada a los elementos de cada array

Descripción

array array_map ( callable $callback , array $array1 [, array $... ] )

array_map() devuelve un array que contiene todos los elementos de array1 después de haber aplicado la función callback a cada uno de ellos. El número de parámetros que la función callback acepte debería coincidir con el número de arrays proporcionados a array_map().

Parámetros

callback

Función de retrollamada a ejecutar para cada elemento de cada array.

array1

Un array a recorrer con la función callback.

...

Lista variable de argumentos de tipo array a recorrer con la función callback.

Valores devueltos

Devuelve un array que contiene todos los elementos de array1 después de aplicar la función callback a cada uno de ellos.

Ejemplos

Ejemplo #1 Ejemplo de array_map()

<?php
function cube($n)
{
    return(
$n $n $n);
}

$a = array(12345);
$b array_map("cube"$a);
print_r($b);
?>

Este ejemplo hace que $b contenga:

Array
(
    [0] => 1
    [1] => 8
    [2] => 27
    [3] => 64
    [4] => 125
)

Ejemplo #2 array_map() usando una función lambda (desde PHP 5.3.0)

<?php
$func 
= function($valor) {
    return 
$valor 2;
};

print_r(array_map($funcrange(15)));
?>
Array
(
    [0] => 2
    [1] => 4
    [2] => 6
    [3] => 8
    [4] => 10
)

Ejemplo #3 array_map() - usando más arrays

<?php
function mostrar_en_español($n$m)
{
    return(
"El número $n se llama $m en español");
}

function 
correspondencia_en_español($n$m)
{
    return(array(
$n => $m));
}

$a = array(12345);
$b = array("uno""dos""tres""cuatro""cinco");

$c array_map("mostrar_en_español"$a$b);
print_r($c);

$d array_map("correspondencia_en_español"$a $b);
print_r($d);
?>

El resultado del ejemplo sería:

// salida de $c
Array
(
    [0] => El número 1 se llama uno en español
    [1] => El número 2 se llama dos en español
    [2] => El número 3 se llama tres en español
    [3] => El número 4 se llama cuatro en español
    [4] => El número 5 se llama cinco en español
)

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

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

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

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

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

)

Usualmente, cuando se usan dos o más arrays, estos deberían ser de la misma longitud, ya que la retrollamada se aplica en paralelo a los elementos correspondientes. Si los arrays son de longitudes diferentes, los más cortos se extenderán con elementos vacíos para que coincidan con la logintud del más largo.

Un uso interesante de esta función es la construcción de un array de arrays, lo que se puede llevar a cabo usando NULL como el nombre de la retrollamada.

Ejemplo #4 Crear un array de arrays

<?php
$a 
= array(12345);
$b = array("one""two""three""four""five");
$c = array("uno""dos""tres""cuatro""cinco");

$d array_map(null$a$b$c);
print_r($d);
?>

El resultado del ejemplo sería:

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
        )

)

Si el argumento array contiene claves de tipo string, el array devuelto tendrá claves de tipo string si y solo si se proporciona exactamente un array. Si se pasa más de un argumento, el array devuelto siempre tendrá claves de tipo integer.

Ejemplo #5 array_map() - con claves de tipo string

<?php
$arr 
= array("stringkey" => "value");
function 
cb1($a) {
    return array (
$a);
}
function 
cb2($a$b) {
    return array (
$a$b);
}
var_dump(array_map("cb1"$arr));
var_dump(array_map("cb2"$arr$arr));
var_dump(array_map(null,  $arr));
var_dump(array_map(null$arr$arr));
?>

El resultado del ejemplo sería:

array(1) {
  ["stringkey"]=>
  array(1) {
    [0]=>
    string(5) "value"
  }
}
array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(5) "value"
    [1]=>
    string(5) "value"
  }
}
array(1) {
  ["stringkey"]=>
  string(5) "value"
}
array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(5) "value"
    [1]=>
    string(5) "value"
  }
}

Ver también

  • array_filter() - Filtra elementos de un array usando una función de devolución de llamada
  • array_reduce() - Reduce iterativamente un array a un solo valor usando una función llamada de retorno
  • array_walk() - Aplicar una función proporcionada por el usuario a cada miembro de un array
  • información acerca de tipos de llamada de retorno

add a note add a note

User Contributed Notes 43 notes

up
19
chreekat
6 years ago
I was miffed that array_map didn't have a way to pass values *and* keys to the callback, but then I realized I could do this:

function callback($k, $v) { ... }

array_map( "callback", array_keys($array), $array);
up
23
gordon dot mcvey at ntlworld dot com
3 years ago
You can use array_map with PHP native functions as well as user functions.  This is very handy if you need to sanitize arrays. 

<?php

$integers
= array_map ('intval', $integers);
$safeStrings = array_map ('mysql_real_escape_string', $unsafeStrings);

?>
up
11
contato at williamsantana dot com dot br
1 year ago
In case of you need to recursively bypass a function over the itens of an array, you can use it

<?php
   
function array_map_recursive($callback, $array) {
        foreach (
$array as $key => $value) {
            if (
is_array($array[$key])) {
               
$array[$key] = array_map_recursive($callback, $array[$key]);
            }
            else {
               
$array[$key] = call_user_func($callback, $array[$key]);
            }
        }
        return
$array;
    }
?>

-----------------------------------------------------------------------

<?php
    $strings
= array(
       
'The',
        array(
           
'quick',
           
'fox',
            array(
               
'brown',
               
'jumps',
                array(
                   
'over',
                    array(
                       
'the',
                        array(
                           
'lazy',
                            array(
                               
'dog'
                           
)
                        )
                    )
                )
            )
        )
    );

   
print_r($strings);
   
$hashedString = array_map_recursive('md5', $strings);
   
print_r($hashedString);
?>

------------------------------------------------------------------------
Testing it, you'll obtain

<?php

/* Original array */

array (
 
0 => 'The',
 
1 =>
  array (
   
0 => 'quick',
   
1 => 'fox',
   
2 =>
    array (
     
0 => 'brown',
     
1 => 'jumps',
     
2 =>
      array (
       
0 => 'over',
       
1 =>
        array (
         
0 => 'the',
         
1 =>
          array (
           
0 => 'lazy',
           
1 =>
            array (
             
0 => 'dog',
            ),
          ),
        ),
      ),
    ),
  ),
);

/* Recursived array */
array (
 
0 => 'a4704fd35f0308287f2937ba3eccf5fe',
 
1 =>
  array (
   
0 => '1df3746a4728276afdc24f828186f73a',
   
1 => '2b95d1f09b8b66c5c43622a4d9ec9a04',
   
2 =>
    array (
     
0 => '6ff47afa5dc7daa42cc705a03fca8a9b',
     
1 => '55947829059f255e4ba2f536a2ae99fe',
     
2 =>
      array (
       
0 => '3b759a9ca80234563d87672350659b2b',
       
1 =>
        array (
         
0 => '8fc42c6ddf9966db3b09e84365034357',
         
1 =>
          array (
           
0 => '0ffe34b4e04c2b282c5a388b1ad8aa7a',
           
1 =>
            array (
             
0 => '06d80eb0c50b49a509b49f2424e8c805',
            ),
          ),
        ),
      ),
    ),
  ),
);

?>

Hope it helps you.

Cheers.
up
13
James
1 year ago
array_map() can be applied to assoc arrays without affecting the keys
up
9
endofyourself at yahoo dot com
9 years ago
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.
up
8
virtual dot greg at gmail dot com
4 years ago
PHP 5.3 enables us to use inline anonymous functions with array_map, cleaning up the syntax slightly.

<?php
$data
= array(
        array(
'id' => 1, 'name' => 'Bob', 'position' => 'Clerk'),
        array(
'id' => 2, 'name' => 'Alan', 'position' => 'Manager'),
        array(
'id' => 3, 'name' => 'James', 'position' => 'Director')
);

$names = array_map(
        function(
$person) { return $person['name']; },
       
$data
);

print_r($names);
?>

This was possible (although not recommended) in prior versions of PHP 5, via create_function().

<?php
$names
= array_map(
       
create_function('$person', 'return $person["name"];'),
       
$data
);
?>

You're less likely to catch errors in the latter version because the code is passed as string arguments.

These are alternatives to using a foreach:

<?php
$names
= array();

foreach (
$data as $row) {
       
$names[] = $row['name'];
}
?>
up
8
Heero
5 years ago
You can easily remove all HTML tags from $_GET or $_POST variables using something like this:

<?php

$_POST
= array_map('strip_tags', $_POST);
$_GET = array_map('strip_tags', $_GET);

?>

This is useful when you don't want to parse HTML.
up
5
radist-hack at yandex dot ru
5 years ago
To transpose rectangular two-dimension array, use the following code:

array_unshift($array, null);
$array = call_user_func_array("array_map", $array);

If you need to rotate rectangular two-dimension array on 90 degree, add the following line before or after (depending on the rotation direction you need) the code above:
$array = array_reverse($array);

Here is example:

<?php
$a
= array(
  array(
1, 2, 3),
  array(
4, 5, 6));
array_unshift($a, null);
$a = call_user_func_array("array_map", $a);
print_r($a);
?>

Output:

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 4
        )

    [1] => Array
        (
            [0] => 2
            [1] => 5
        )

    [2] => Array
        (
            [0] => 3
            [1] => 6
        )

)
up
3
pmf
6 years ago
This function behaves exactly like array_map but additionally does not reject non-array arguments. Instead, it transforms them with the array_fill function to a constant valued array of required length according to the other array arguments (if any) and executes the original array_map function.

<?php

function array_map2() {
   
$args = func_get_args();

   
$callback = array_shift($args);
   
   
$args = array_map(
           
create_function('$a,$max','return is_array($a)? $a: array_fill(0,$max,$a);'),
           
$args,array_fill(0,count($args),array_reduce($args,
           
create_function('$v,$w','return max($v,is_array($w)? count($w): 1);'))));

   
array_unshift($args,$callback);
   
    return
call_user_func_array("array_map",$args);
}

?>

Example:

<?php

$get
= "first=value1&second=value2&third=value3";

print_r(array_map2("explode","=",explode("&",$get)));

?>

would print out:

<?php

Array
(
    [
0] => Array
        (
            [
0] => first
           
[1] => value1
       
)

    [
1] => Array
        (
            [
0] => second
           
[1] => value2
       
)

    [
2] => Array
        (
            [
0] => third
           
[1] => value3
       
)
)

?>

/pmf
up
2
henrique at webcoder dot com dot br
6 years ago
Adding method support to function by Andref (multidimensionalArrayMap).

function array_map_r( $func, $arr )
{
    $newArr = array();
   
    foreach( $arr as $key => $value )
    {
        $newArr[ $key ] = ( is_array( $value ) ? array_map_r( $func, $value ) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value ) ) );
    }
       
    return $newArr;
}

array_map_r('function', array());
or
array_map_r(array('class', 'method'), array());
up
1
php/hotblocks/nl
2 years ago
Note that the $arr argument has to be an array, not just a Traversable/Iterator.

For instance this won't work:

<?php

$documents
= $mongo->db->collection->find();
// $documents is Traversable by foreach

$ids = array_map(function($document) {
  return
$document['_id'];
},
$objects);
// $ids will now be NULL, because $documents wasn't an Array

?>

A solution is to first use iterator_to_array():

<?php

$ids
= array_map(function($document) {
  return
$document['_id'];
},
iterator_to_array($objects));
// $ids will now be an array of ['_id']s

?>

But this is not very efficient: two cycles instead of one. Another solution is to use foreach: one cycle and a lot of freedom (and in the same scope).
up
1
galenjr at gmail dot com
5 years ago
Another way to array_map htmlentities with a specific quote style is to create a function that does it and map that function

<?php

function map_entities( $str ) {
    return
htmlentities( $str, ENT_QUOTES );
}
$good_array = array_map ( 'map_entities', $bad_array );

?>
up
1
loaded67 at hotmail dot com
6 years ago
this function is really nice for recursion in php!!!

example in a class:

<?php
class test{

   
//private $container = array();
   
   
final public function add($key, $value){
        
/* recursion */
        
if(is_array($value)){
              
array_map(array($this, __FUNCTION__), array_keys($value), array_values($value));
         }
        
/* procedural */
        
else{
             echo
$key.' => '.$value.'<br/>'.PHP_EOL;
            
// do stuff...
             // if(!isset($this->container[$key])){
             //       $this->container[$key] = $value;
             // }
             //else{  // trigger_error() xor throw new Exception?
             //         echo 'allready exists!<br/>'.PHP_EOL;
             //}
        
}
    }
}
//
$array = array (
                              
'one'   => 'value1',
                              
'two'   => 'value2',
                              
'three' => 'value3'
                           
);

$t = new test;
$t->add($array);
?>

you could easiely do this without a class too offcourse!
used in php 5.2.5
up
2
moester at gmail dot com
6 years ago
Wish this was built in.  Mimics Ruby and Prototype's array pluck function.  Returns specific key/column from an array of objects.

<?php
function array_pluck($key, $array)
{
    if (
is_array($key) || !is_array($array)) return array();
   
$funct = create_function('$e', 'return is_array($e) && array_key_exists("'.$key.'",$e) ? $e["'. $key .'"] : null;');
    return
array_map($funct, $array);
}

// usage:

$a = array(array("id"=>10, "name"=>"joe"), array("id"=>11, "name"=>"bob"));

$ids = array_pluck("id", $a);        // == array(10,11)
$names = array_pluck("name", $a);    // == array("joe", "bob")

//works on non-keyed arrays also:

$a = array(array(3,4), array(5,6));
$col2 = array_pluck(1,$a);            // == array(4,6) (grab 2nd column of data)

?>
up
1
nd0 at gmx dot de
10 years ago
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
)
up
1
shakespeare32 at gmail dot com
1 year ago
Why not an array of callbacks?

<?php
function array_maps($callbacks, $array) {
    if (!
$callbacks) { return $array; }
   
    if (!
is_array($callbacks) && is_string($callbacks) && function_exists($callbacks)) {
        return
array_map($callbacks, $array);
    }

    foreach(
$callbacks as $callback) {
        if (
function_exists($callback)) {
       
$array = array_map($callback, $array);
        }
    }

    return
$array;
}
?>
up
2
elfe1021 at gmail dot com
9 months ago
Find an interesting thing that in array_map's callable function, late static binding does not work:
<?php
class A {
    public static function
foo($name) {
        return
'In A: '.$name;
    }

    public static function
test($names) {
        return
array_map(function($n) {return static::foo($n);}, $names);
    }
}

class
B extends A{
    public static function
foo($name) {
        return
'In B: '.$name;
    }
}

$result = B::test(['alice', 'bob']);
var_dump($result);
?>

the result is:
array (size=2)
  0 => string 'In A: alice' (length=11)
  1 => string 'In A: bob' (length=9)

if I change A::test to
<?php
   
public static function test($names) {
        return
array_map([get_called_class(), 'foo'], $names);
    }
?>

Then the result is as expected:
array (size=2)
  0 => string 'In B: alice' (length=11)
  1 => string 'In B: bob' (length=9)
up
1
stephen at mu dot com dot au
11 years ago
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.
up
2
stijnleenknegt at gmail dot com
6 years ago
If you want to pass an argument like ENT_QUOTES to htmlentities, you can do the follow.

<?php
$array
= array_map( 'htmlentities' , $array, array_fill(0 , count($array) , ENT_QUOTES) );
?>

The third argument creates an equal sized array of $array filled with the parameter you want to give with your callback function.
up
1
lukasz dot mordawski at gmail dot com
9 months ago
Let's assume we have following situation:

<?php
class MyFilterClass {
    public function
filter(array $arr) {
        return
array_map(function($value) {
            return
$this->privateFilterMethod($value);
        });
    }

    private function
privateFilterMethod($value) {
        if (
is_numeric($value)) $value++;
        else
$value .= '.';
    }
}
?>

This will work, because $this inside anonymous function (unlike for example javascript) is the instance of MyFilterClass inside which we called it.
I hope this would be useful for anyone.
up
1
CertaiN
1 year ago
The most memory-efficient array_map_recursive().

<?php
function array_map_recursive(callable $func, array $arr) {
   
array_walk_recursive($arr, function(&$v) use ($func) {
       
$v = $func($v);
    });
    return
$arr;
}
?>
up
1
kelly m
4 years ago
I realize this function is easy enough to make, but this is a faster version (twice the speed) of [a function] which I find incredibly useful.

<?php
function array_pluck($key, $input) {
    if (
is_array($key) || !is_array($input)) return array();
   
$array = array();
    foreach(
$input as $v) {
        if(
array_key_exists($key, $v)) $array[]=$v[$key];
    }
    return
$array;
}
?>

Usage:

<?php $ids = array_pluck('id', $users); ?>
up
1
onassar at gmail dot com
4 years ago
Wrote up my own key preservation function for array mapping. It allows n arguments to be passed, and should be easy enough to follow if you need to make any mods. If you've got any thoughts let me know.

<?php
       
/**
         * arrayMap function. Customized array_map function which preserves keys/associate array indexes.
         *
         * @access public
         * @param callback $callback Callback function to run for each element in each array.
         * @param mixed $arr1 An array to run through the callback function.
         * @param array $array Variable list of array arugments to run through the callback function.
         * @return array Array containing all the elements of $arr1 after applying the callback function to each one, recursively, maintain keys.
         */
       
function arrayMap($callback,$arr1) {
           
$results       =    array();
           
$args          =    array();
            if(
func_num_args()>2)
               
$args          =    (array) array_shift(array_slice(func_get_args(),2));
            foreach(
$arr1 as $key=>$value) {
                if(
is_array($value)) {
                   
array_unshift($args,$value);
                   
array_unshift($args,$callback);
                   
$results[$key]    =    call_user_func_array(array('self','arrayMap'),$args);
                }
                else {
                   
array_unshift($args,$value);
                   
$results[$key]    =    call_user_func_array($callback,$args);
                }
            }
            return
$results;
        }
?>
up
0
wapinet at mail dot ru
2 months ago
PHP 5.5.14
<?php
$columns
= range(1, 100000);
$time = microtime(true);

/*
0.067003011703491 sec
24903680 byte
*/
array_map(function ($value) {
    return
'p.' . $value;
},
$columns);

/*
0.042001962661743 sec
19398656 byte
*/
foreach ($columns as $key => $column) {
   
$columns[$key] = 'p.' . $column;
}

/*
0.05500316619873 sec
10747904 byte
*/
array_walk($columns, function (&$value, $key) {
   
$value = 'p.' . $value;
});

/*
0.0260009765625 sec
10747904 byte
*/
foreach ($columns as &$column) {
   
$column = 'p.' . $column;
}

echo
microtime(true) - $time . "\n" . memory_get_peak_usage(true) . "\n";
up
0
ian_channing at hotmail dot com
7 months ago
I wanted a nice way to convert an array with x values as keys and y values as values e.g. array(x => y,...) into x,y co-ordinates e.g. array(array(x,y), ...).

You can do:

<?php
foreach ($waveform as $key => $waveformPoint) {
   
$coordinates[] = array($key, $waveformPoint);
}
?>

But array_map with a null callback gives you a nicer way:

<?php
$coordinates
= array_map(null, array_keys($waveform), array_values($waveform));
?>
up
0
williamprogphp at yahoo dot com dot br
7 months ago
A function to map an array working also with its key.

<?php
   
function array_mapk($callback, $array) {
       
$newArray = array();
        foreach (
$array as $k => $v) {
           
$newArray[$k] = call_user_func($callback, $k, $v);
        }
        return
$newArray;
    }
?>

Usage:

<?php
    $dados
= array();
   
$dados['cep'] = "32340-070";
   
$dados['initial'] = 100;
   
$dados['final'] = 300;
   
$dados['processed'] = 1;

    echo
"update table set " . implode(", ", array_mapk(function ($k, $v) { return "{$k} = '" . mysql_real_escape_string($v) . "'"; }, $dados));
?>

Cheers.
up
0
jessiedeer at hotmail dot com
1 year ago
array_map becomes interesting and faster than foreach when used with existing PHP functions.

Example:

$arr1 = array(1, 2, 3, 4);
$arr2 = array(4, 3, 2, 1);

// array with min values for each key
print_r(array_map("min", $arr1, $arr2));

Result: Array ( [0] => 1 [1] => 2 [2] => 2 [3] => 1 )

// array with max values for each key
print_r(array_map("max", $arr1, $arr2));

Result: Array ( [0] => 4 [1] => 3 [2] => 3 [3] => 4 )
up
0
Anonymous
1 year ago
Simple yet effective associative version of map that accepts arbitrary number of arrays.
Instead of elements, result from each() get passed as function arguments.

<?php
function array_map_assoc(){
    if(
func_num_args() < 2) throw new \BadFuncionCallException('Missing parameters');
   
$args = func_get_args();
   
$callback = $args[0];
    if(!
is_callable($callback)) throw new \InvalidArgumentException('First parameter musst be callable');
   
$arrays = array_slice($args, 1);
   
array_walk($arrays, function(&$a){
       
$a = (array)$a;
       
reset($a);
    });
   
$results = array();
   
$max_length = max(array_map('count', $arrays));
   
$arrays = array_map(function($pole) use ($max_length){
        return
array_pad($pole, $max_length, null);
    },
$arrays);
    for(
$i=0; $i < $max_length; $i++){
       
$elements = array();
        foreach(
$arrays as &$v){
           
$elements[] = each($v);
        }
        unset(
$v);
       
$out = call_user_func_array($callback, $elements);
        if(
$out === null) continue;
       
$val = isset($out[1]) ? $out[1] : null;
        if(isset(
$out[0])){
           
$results[$out[0]] = $val;
        }else{
           
$results[] = $val;
        }
    }
    return
$results;
}

//USAGE:
$days = array('Sun' => 'Sunday', 'Mon' => 'Monday', 'Tue' => 'Tuesday', 'Wed' => 'Wednesday', 'Thu' => 'Thursday', 'Fri' => 'Friday', 'Sat' => 'Saturday');
$nums = array('First', 'Second', 'Third', 'Fourth', 'Fifth', 'Sixth', 'Seventh');

$result = array_map_assoc(function($a, $b){
    return array(
$b['value'], $a['key']);
},
$days, $nums);

var_dump($result);

//RESULT:
array (size=7)
 
'First' => string 'Sun' (length=3)
 
'Second' => string 'Mon' (length=3)
 
'Third' => string 'Tue' (length=3)
 
'Fourth' => string 'Wed' (length=3)
 
'Fifth' => string 'Thu' (length=3)
 
'Sixth' => string 'Fri' (length=3)
 
'Seventh' => string 'Sat' (length=3)
up
0
hrvoj3e at gmail dot com
1 year ago
Why not use

mb_convert_case($str, MB_CASE_TITLE, "UTF-8");

Works for me! :)
up
1
pcdinh at phpvietnam dot net
8 years ago
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.
up
0
godek dot maciek at gmail dot com
2 years ago
I came up with a convenient syntax for method application, particularly useful inside the array_map.
For instance, if you want to
array_map(function($object, $arg1) { return $object->method($arg1, "arg2"); }, $objects, $args1);

it is possible to provide a shorthand:
global $_; // necessary inside a function, unfortunately

array_map($_->method($_, "arg2"), $objects, $args1);

Here's the implementation (works with 5.3)

function m_caller($method) {
  $args = func_get_args();
  array_shift($args);
  return function($object) use($method, $args) {
    global $_;
    $local_args = func_get_args();
    array_shift($args);
    if(!is_object($object)) {
      // error                                                                                                                                                                                                
    }
    $reflection = new ReflectionMethod(get_class($object), $method);
    foreach($args as $key => $arg) {
      if($arg === $_) {
        $args[$key] = array_shift($local_args);
      }
    }
    return $reflection->invokeArgs($object, array_merge($args, $local_args));
  };
}

class MethodCaller {
  public function __call($name, $arguments) { return call_user_func_array('m_caller', array_merge(array($name), $arguments)); }
  public function __get($name) { return m_caller($name); }
};

$_ = new MethodCaller();
up
0
qeremy
2 years ago
An alternative for recursive mapping;

<?php
function array_map_recursive($fn, $arr) {
   
$rarr = array();
    foreach (
$arr as $k => $v) {
       
$rarr[$k] = is_array($v)
            ?
array_map_recursive($fn, $v)
            :
$fn($v); // or call_user_func($fn, $v)
   
}
    return
$rarr;
}

function
sqr($x) {
    return
"$x ^ 2 = ". ($x * $x);
}

$a = array(1, 2, 3, array(4, array(5)));
$b = array_map_recursive("sqr", $a);
print_r($b);
?>

Array
(
    [0] => 1 ^ 2 = 1
    [1] => 2 ^ 2 = 4
    [2] => 3 ^ 2 = 9
    [3] => Array
        (
            [0] => 4 ^ 2 = 16
            [1] => Array
                (
                    [0] => 5 ^ 2 = 25
                )

        )

)
up
0
gmail.com@mspreij
2 years ago
Hope I'm not late to the party, here's my function to apply array_map to the *keys* of an array.
Extra array arguments will be used for the callback function's parameters just like with array_map, with the difference that a string is also allowed: it will just be used to create an array of appropriate length with as each value that string. Arrays are left alone (and will be padded with nulls by array_map as needed).

<?php

//_________________________________________________
// array_map_keys($callback, $array, [$args, ..]) /
function array_map_keys($callback, $array /* [, $args ..] */) {
 
$args = func_get_args();
  if (!
is_callable($callback)) trigger_error("first argument (callback) is not a valid function", E_USER_ERROR);
  if (!
is_array($array)) trigger_error("second argument must be an array", E_USER_ERROR);
 
$args[1] = array_keys($array);
 
// If any additional arguments are not arrays, assume that value is wanted for every $array item.
  // array_map() will pad shorter arrays with Null values
 
for ($i=2; $i < count($args); $i++) {
    if (!
is_array($args[$i])) {
     
$args[$i] = array_fill(0, count($array), $args[$i]);
    }
  }
  return
array_combine(call_user_func_array('array_map', $args), $array);
}

// Some examples:

$arr = array('foo'=>123, 'bar'=>456);

// simply uppercase keys:
var_dump(array_map_keys('strtoupper', $arr));
// or..
var_dump(array_map_keys(function($input) {return strtoupper($input);}, $arr));
// >> array(2) { ["FOO"]=>int(123) , ["BAR"]=> int(456) }

// Add a prefix 'myvar_':
var_dump(array_map_keys(function($input, $prefix) {return $prefix.$input;}, $arr, 'myvar_'));
// >> array(2) { ["myvar_foo"]=>int(123) , ["myvar_bar"]=>int(456) }

// Apart from the (static string) prefix, we also number them:
$arr = array('foo'=>123, 'bar'=>456, 'bazz'=>789, 'yadda'=>'0AB');
var_dump(array_map_keys(function($input, $middle, $number) {return $number.':'.$middle.$input;}, $arr, 'myvar_', range(1, count($arr))));
// >> array(4) { ["1:myvar_foo"]=>int(123) , ["2:myvar_bar"]=>int(456) , ["3:myvar_bazz"]=>int(789) , ["4:myvar_yadda"]=>string(3) "0AB" }

?>
up
1
Vinicius Cubas Brand
9 years ago
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
)
up
0
onassar at gmail dot com
4 years ago
Fixed a bug with array recursion.

<?php
       
/**
         * arrayMap function. Customized array_map function which preserves keys/associate array indexes. Note that this costs a descent amount more memory (eg. 1.5k per call)
         *
         * @access public
         * @param callback $callback Callback function to run for each element in each array.
         * @param mixed $arr1 An array to run through the callback function.
         * @param array $array Variable list of array arugments to run through the callback function.
         * @return array Array containing all the elements of $arr1 after applying the callback function to each one, recursively, maintain keys.
         */
       
function arrayMap($callback,$arr1) {
           
$results       =    array();
           
$args          =    array();
            if(
func_num_args()>2)
               
$args          =    (array) array_shift(array_slice(func_get_args(),2));
            foreach(
$arr1 as $key=>$value) {
               
$temp    =    $args;
               
array_unshift($temp,$value);
                if(
is_array($value)) {
                   
array_unshift($temp,$callback);
                   
$results[$key]    =    call_user_func_array(array('self','arrayMap'),$temp);
                } else {
                   
$results[$key]    =    call_user_func_array($callback,$temp);
                }
            }
            return
$results;
        }
?>
up
0
GUI
6 years ago
The following takes an array of objects, and returns the result of calling a member function on each object. So if I have an array of objects that all have a getName() method, calling array_map_objects("getName", $thingies) will return the array filled with the getName() value for each object.

<?php
function array_map_objects($member_function, $array) {
   
$values = array();

    if(
is_string($member_function) && is_array($array)) {
       
$callback = create_function('$e', 'return call_user_func(array($e, "' . $member_function .'"));');
       
$values = array_map($callback, $array);
    }

    return
$values;
}
?>
up
0
jo at ho dot nl
6 years ago
Could also use things like...

array_keys(); and array_values(); offcourse...

However it's just an example off recursion via this function..
Which I found pretty handy at times dealing with arrays..

could also use:

<?php
call_user_func
(array($this, __FUNCTION), $args);
?>

or

<?php
call_user_fuc_array
(array($this, __FUNCTION__), $array);
?>

or

<?php
class{

   public function
__construct($arg){
       if(
is_array($arg)){
            new
self($arg);
       }
       else{
           echo
$arg.'<br/>'.PHP_EOL;
       }
   }
}
?>

Anyway.. plenty off examples..
It was just an idea for others...
up
-1
JacobA dot Barber at yahoo dot com
4 months ago
Here is an example for php 5.4 and greater, using a closure:
<?php
$myList
= [1,2,3,4];

$mappedList = array_map(function($value){
    return
$value * 2;
},
$myList);

var_dump($mappedList);

array(
4) {
  [
0]=>int(2)
  [
1]=>int(4)
  [
2]=>int(6)
  [
3]=>int(8)
}
?>
This is useful when you don't want/need to define a function just so it can be used with the map function.
up
0
bturchik at iponweb dot net
7 years ago
Maybe this one will be useful for someone:

function array_map_helper($mapper, $array) {
    $mapper = preg_replace('/^return (.*?);$/', '$1', trim($mapper));
    $result = array();
    if (preg_match('/(\(?)(.*?)\s*=>\s*(.*?)(\)?)$/', $mapper, $matches)) {
        list($full_found, $array_open, $left, $right, $array_close) = $matches;
        if ($array_open && $array_close) {
            $mapper = '$result[] = array' . $full_found . ';';
        } else {
            $mapper = '$result[' . $left . '] = ' . $right . ';';
        }
    } else {
        $mapper = '$result[] = ' . $mapper . ';';
    }

    foreach ($array as $key => $value) {
        eval($mapper);
    }

    return $result;
}

should be used like:

$array = array(array('foo' => 11, 'bar' => 22),
               array('foo' => 111, 'bar' => 222),
               array('foo' => 1111, 'bar' => 2222));
$mapped = array_map_helper('$value["foo"] => $value["bar"]', $array);

var_dump will give

array(3) {
  [11]=>
  int(22)
  [111]=>
  int(222)
  [1111]=>
  int(2222)
}

or

$mapped = array_map_helper('$value["foo"]', $array);

var_dump will give

array(3) {
  [0]=>
  int(11)
  [1]=>
  int(111)
  [2]=>
  int(1111)
}

or

$mapped = array_map_helper('$value["foo"] + $value["bar"] . " at position $key"', $array);

var_dump will give

array(3) {
  [0]=>
  string(16) "33 at position 0"
  [1]=>
  string(17) "333 at position 1"
  [2]=>
  string(18) "3333 at position 2"
}
up
-1
jessiedeer at hotmail dot com
1 year ago
array_map becomes interesting and faster than foreach when used with existing PHP functions.

Example:

$arr1 = array(1, 2, 3, 4);
$arr2 = array(4, 3, 2, 1);

// array with min values for each key
print_r(array_map("min", $arr1, $arr2));

Result: Array ( [0] => 1 [1] => 2 [2] => 2 [3] => 1 )

// array with max values for each key
print_r(array_map("max", $arr1, $arr2));

Result: Array ( [0] => 4 [1] => 3 [2] => 3 [3] => 4 )
up
0
andref dot dias at pronus dot eng dot br
7 years ago
A recursive way to handle multidimensional arrays:

<?php

function multidimensionalArrayMap( $func, $arr )
    {
   
$newArr = array();
    foreach(
$arr as $key => $value )
        {
       
$newArr[ $key ] = ( is_array( $value ) ? multidimensionalArrayMap( $func, $value ) : $func( $value ) );
        }
    return
$newArr;
    }

?>
up
0
Anonymous
9 years ago
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
    )
)
up
-1
david dot tulloh at infaze dot com dot au
9 years ago
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
)
To Top