PHP Conference Japan 2024

array_map

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

array_map將回呼函式應用於指定陣列的元素

說明

array_map(?callable $callback, array $array, array ...$arrays): array

array_map() 會傳回一個 陣列,其中包含將 callback 應用於對應 array 值(以及如果提供更多陣列則為 arrays)的結果,這些值將作為 callback 的引數。 callback 函式接受的參數數量應與傳遞給 array_map() 的陣列數量相符。多餘的輸入陣列會被忽略。如果提供的引數數量不足,則會拋出 ArgumentCountError

參數

callback

要對每個陣列中的每個元素執行的 可呼叫 函式。

可以將 null 作為值傳遞給 callback,以對多個陣列執行 zip 操作,並傳回一個陣列,其元素皆為一個陣列,其中包含相同索引的輸入陣列的元素(請參見下面的範例)。如果只提供 arrayarray_map() 將會傳回輸入陣列。

array

要透過 callback 函式執行的陣列。

arrays

要透過 callback 函式執行的補充陣列引數列表。

傳回值

傳回一個陣列,其中包含將 callback 函式應用於對應 array 值(以及如果提供更多陣列則為 arrays)的結果,這些值將作為 callback 的引數。

若且唯若只傳遞一個陣列,傳回的陣列才會保留陣列引數的鍵。如果傳遞多個陣列,傳回的陣列將具有連續的整數鍵。

更新日誌

版本 說明
8.0.0 如果 callback 預期透過參考傳遞參數,此函式現在將發出 E_WARNING

範例

範例 #1 array_map() 範例

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

$a = [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 使用 lambda 函式的 array_map()

<?php
$func
= function(int $value): int {
return
$value * 2;
};

print_r(array_map($func, range(1, 5)));

// 或從 PHP 7.4.0 開始:

print_r(array_map(fn($value): int => $value * 2, range(1, 5)));

?>
Array
(
    [0] => 2
    [1] => 4
    [2] => 6
    [3] => 8
    [4] => 10
)

範例 #3 array_map() - 使用更多陣列

<?php
function show_Spanish(int $n, string $m): string
{
return
"數字 {$n} 的西班牙文是 {$m}";
}

function
map_Spanish(int $n, string $m): array
{
return [
$n => $m];
}

$a = [1, 2, 3, 4, 5];
$b = ['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] => The number 1 is called uno in Spanish
    [1] => The number 2 is called dos in Spanish
    [2] => The number 3 is called tres in Spanish
    [3] => The number 4 is called cuatro in Spanish
    [4] => The number 5 is called cinco in Spanish
)

// 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 作為回呼函式的名稱輕鬆完成。

範例 #4 執行陣列的壓縮 (zip) 操作

<?php
$a
= [1, 2, 3, 4, 5];
$b = ['one', 'two', 'three', 'four', 'five'];
$c = ['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
        )

)

範例 #5 使用 null 作為 callback 且僅帶有 array 參數

<?php
$array
= [1, 2, 3];
var_dump(array_map(null, $array));
?>

上述範例會輸出:

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

範例 #6 array_map() - 使用字串鍵名

<?php
$arr
= ['stringkey' => 'value'];
function
cb1($a) {
return [
$a];
}
function
cb2($a, $b) {
return [
$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));
?>

上述範例會輸出:

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"
  }
}

範例 #7 array_map() - 關聯式陣列 (Associative Arrays)

雖然 array_map() 並不直接支援使用陣列鍵名作為輸入,但可以透過 array_keys() 來模擬。

<?php
$arr
= [
'v1' => 'First release',
'v2' => 'Second release',
'v3' => 'Third release',
];

// 注意:在 7.4.0 之前的版本,請使用較長的匿名函式語法。
$callback = fn(string $k, string $v): string => "$k was the $v";

$result = array_map($callback, array_keys($arr), array_values($arr));

var_dump($result);
?>

上述範例會輸出:

array(3) {
  [0]=>
  string(24) "v1 was the First release"
  [1]=>
  string(25) "v2 was the Second release"
  [2]=>
  string(24) "v3 was the Third release"
}

另請參閱

  • array_filter() - 使用回呼函式篩選陣列元素
  • array_reduce() - 使用回呼函式迭代地將陣列簡化為單一值
  • array_walk() - 將使用者提供的函式應用於陣列的每個成員

新增註解

使用者貢獻的註解 8 則註解

31
lukasz dot mordawski at gmail dot com
11 年前
假設我們有以下情況

<?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(與例如 JavaScript 不同)是我們在其中呼叫它的 MyFilterClass 的實例。
我希望這對任何人都有幫助。
20
radist-hack at yandex dot ru
16 年前
要轉置矩形二維陣列,請使用以下程式碼:

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

如果您需要將矩形二維陣列旋轉 90 度,請在上述程式碼之前或之後(取決於您需要的旋轉方向)新增以下程式碼:
$array = array_reverse($array);

以下是範例:

<?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);
?>

輸出:

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

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

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

)
16
Mahn
9 年前
您可能正在尋找一種方法,除了 for/foreach 迴圈之外,還能根據條件從多維陣列中提取值(例如 array_map 和 array_filter 的混合使用)。如果是這樣,您可以利用以下事實:1) 如果沒有明確指定回傳值,array_map 的回呼方法會返回 null(與其他所有方法一樣);2) 沒有引數的 array_filter 會移除假值。

例如,假設您有:

<?php
$data
= [
[
"name" => "John",
"smoker" => false
],
[
"name" => "Mary",
"smoker" => true
],
[
"name" => "Peter",
"smoker" => false
],
[
"name" => "Tony",
"smoker" => true
]
];
?>

您可以使用以下單行程式碼提取所有非吸菸者的姓名:

<?php
$names
= array_filter(array_map(function($n) { if(!$n['smoker']) return $n['name']; }, $data));
?>

它不一定比 for/foreach 迴圈更好,但偶爾使用單行程式碼來處理瑣碎的任務可以幫助保持程式碼的簡潔性。
3
s dot kientzler at online dot de
1 年前
如果要呼叫的回呼函式是來自不同命名空間的靜態方法,則必須指定包含命名空間的完整合格方法(單獨使用 use 陳述式不足以解析回呼函式的命名空間)。

<?php
use MyTools;

$arr = [1, 2, 3];

$arr = array_map('Tools::myHelper', $arr);
?>

會造成型別錯誤 (TypeError)
array_map() 預期參數 1 為有效的回呼函式,找不到類別 'Tools'。

請改用完整的命名空間來指定回呼函式

<?php
$arr
= [1, 2, 3];

$arr = array_map('\MyTools\Tools::myHelper', $arr);
?>
8
CertaiN
11 年前
最有效率使用記憶體的 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;
}
?>
8
stijnleenknegt at gmail dot com
16 年前
如果您想傳遞像 ENT_QUOTES 這樣的參數給 htmlentities,您可以這樣做。

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

第三個參數會建立一個與 $array 大小相同的陣列,並以您想傳遞給回呼函式的參數填滿。
2
Walf
2 年前
一個通用的解決方案,用於處理想要在回呼函式中知道鍵值,以及/或者在返回的陣列中保留鍵值關聯的問題。

<?php

/**
* 類似 array_map(),但回呼函式也會接收目前的鍵作為
* 第一個參數,如下所示:
* function($key, $val, ...$vals) { ... }
* ... 而且返回的陣列始終保持鍵關聯,即使傳遞了多個
* 陣列參數。
*/

function array_map_assoc(callable $callback, array $array, array ...$arrays) {
$keys = array_keys($array);
array_unshift($arrays, $keys, $array);
return
array_combine($keys, array_map($callback, ...$arrays));
}

?>

因為它直接使用 array_map(),所以在忽略後續陣列參數的鍵方面,它的行為方式相同。它也具有相同的可變參數簽章。
1
匿名使用者
2 年前
/**
* 遞迴地將回呼函式應用於所有值及其
* 鍵的函式,並返回具有更新鍵和
* 值的結果陣列副本。
* PHP 的內建函式 array_walk_recursive() 只將傳遞的
* 回呼函式應用於陣列值,而不是鍵,因此此函式只是將
* 回呼函式也應用於鍵(因此需要使用副本,
* 因為更新鍵也會導致原始
* 陣列的參考丟失)。我需要這樣的東西,因此我想到在這裡分享它。
*
* @param callable $func 接收一個參數(要更新的值
* 或鍵)並返回其
* 更新值的回呼函式
*
* @param array $arr 鍵和值將被
* 更新的陣列
*/

function array_map_recursive(
callable $func,
array $arr
) {

) { // end of parameter list
// 初始化複製的陣列,它將保存所有更新的鍵和值

$result = [];
// 迭代陣列的鍵值對

foreach ( $arr as $key => $value ) {
// 將回呼函式應用於鍵以創建更新的鍵值

$updated_key = $func( $key );
// 如果迭代的值不是陣列,則表示我們已到達迭代鍵的
// 最深陣列級別,因此在這種情況下,將
// 更新的值賦值給最終輸出陣列中更新的鍵值

if ( ! is_array( $value ) ) {

$result[$updated_key] = $func( $value );

} else {
// 如果迭代的值是一個陣列,則遞迴調用該函式,
// 將當前迭代的值作為 $arr 參數
$result[$updated_key] = array_map_recursive(
$func,
);

}

);

} // 鍵值對迭代結束
// 最後,返回生成的結果集

return $result;
To Top