我正在使用 PHP 中的 map,代码如下:
function func($v) {
return $v * 2;
}
$values = array(4, 6, 3);
$mapped = array_map(func, $values);
var_dump($mapped);
在函数中是否可以获取值的索引?
另外,如果我编写需要索引的代码,是应该使用for循环还是map?
我正在使用 PHP 中的 map,代码如下:
function func($v) {
return $v * 2;
}
$values = array(4, 6, 3);
$mapped = array_map(func, $values);
var_dump($mapped);
在函数中是否可以获取值的索引?
另外,如果我编写需要索引的代码,是应该使用for循环还是map?
当然可以,借助于array_keys()
函数:
function func($v, $k)
{
// key is now $k
return $v * 2;
}
$values = array(4, 6, 3);
$mapped = array_map('func', $values, array_keys($values));
var_dump($mapped);
在对匿名数组执行匿名函数映射时,无法访问键:
array_map(
function($val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
array_reduce 也不能访问键。array_walk 可以访问键,但是数组是通过引用传递的,这需要一层间接。
一些解决方案包括:
这很糟糕,因为我们改变了原始数组。而且“array()”调用的样板文件会随着数组长度的增加而线性增加:
array_map(
function($pair) use ($foo) {
list($key, $val) = $pair;
/* ... */
},
array(array(key1, val1),
array(key2, val2),
/* ... */));
我们在原始数组上进行操作,模板是恒定的,但是我们可以轻松地覆盖现有的变量:
$i_hope_this_does_not_conflict = array(key1 => val1,
key2 => val2,
/* ... */);
array_map(
function($key, $val) use ($foo) { /* ... */ },
array_keys($i_hope_this_does_not_conflict),
$i_hope_this_does_not_conflict);
unset($i_hope_this_does_not_conflict);
我们可以利用函数作用域来防止覆盖现有名称,但必须添加额外的 "use" 层级:
call_user_func(
function($arr) use ($foo) {
return array_map(function($key, $val) use ($foo) { /* ... */ },
array_keys($arr),
$arr);
},
array(key1 => val1,
key2 => val2,
/* ... */));
我们在原始作用域中定义要映射的函数,以避免“use”样板代码:
call_user_func(
function($f, $arr) {
return array_map($f, array_keys($arr), $arr);
},
function($key, $val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
有趣的是,我们上一个一次性函数具有良好的通用签名,看起来很像array_map。我们可能想要给它一个名称并重复使用:
function array_mapk($f, $arr) {
return array_map($f, array_keys($arr), $arr);
}
我们的应用程序代码变成:
array_mapk(
function($key, $val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
在上述内容中,我忽略了array_walk函数,因为它要求通过引用传递参数;然而,我后来意识到可以使用call_user_func轻松解决这个问题。我认为这是迄今为止最好的版本:
call_user_func(
'array_walk',
array(key1 => val1,
key2 => val2,
/* ... */),
function($val, $key) use ($foo) { /* ... */ });
在 array_map
回调函数中无法访问索引。如果您正在使用连续的数字索引,则可以使用递增的静态变量:
$values = ["one", "two", "three"];
$mapped = array_map(function ($value) {
static $i = 0;
$result = "Index: $i, Value: $value";
$i++;
return $result;
}, $values);
print_r($mapped);
Array
(
[0] => Index: 0, Value: one
[1] => Index: 1, Value: two
[2] => Index: 2, Value: three
)
这是一个有点老的帖子,但和许多人一样,我正在使用array_keys
函数:
array_map(function($id, $name) {
print '<option value="'.$id.'">'.$name.'</option>';
}, array_keys($array), array_values($array));
array_map
函数的第二个参数中,您可以添加两个数组代替use
关键字。我认为不需要进行解释,这段代码非常简单。array_values($array)
可以安全地替换为 $array
。如果您不打算使用 array_map()
的 return
,那么您可能不应该调用 array_map()
。很可能 array_walk()
更适合。 - mickmackusause()
或global
(我推荐前者)来允许从回调函数内部访问原始数组。$values = [4, 6, 3];
var_export(
array_map(
fn($k) => "$k: " . $values[$k] * 2,
array_keys($values)
)
);
foreach()
并通过引用修改值。(演示)$values = [4, 6, 3];
foreach ($values as $k => &$v) {
$v = "$k: " . $v * 2;
}
var_export($values);
非常简单:
只需使用array_map函数:没有索引键!
$params = [4,6,2,11,20];
$data = array_map(function($v) { return ":id{$v}";}, $params);
array (size=5)
0 => string ':id4' (length=4)
1 => string ':id6' (length=4)
2 => string ':id2' (length=4)
3 => string ':id11' (length=5)
4 => string ':id20' (length=5)
$data = array_map(
function($k) use ($params) { return ":id{$k}_${params[$k]}"; },
array_keys($params)
);
array (size=5)
0 => string ':id0_4' (length=6)
1 => string ':id1_6' (length=6)
2 => string ':id2_2' (length=6)
3 => string ':id3_11' (length=7)
4 => string ':id4_20' (length=7)
function func($v, $index) {
return $v * 2;
}
$values = array(4, 6, 3);
$valuesIndex = range(0, count($values) - 1);
$mapped = array_map(func, $values, $valuesIndex);
var_dump($mapped);
func
常量的定义。你没有测试这段代码。请在发布到 Stack Overflow 之前在 3v4l.org 上测试你的代码片段。 - mickmackusarange(0, count($values) - 1)
)来生成已经生成的数据并不是一个好主意。只需使用array_keys()
访问已经可用的内容即可。 - mickmackusa对于一个快速且开放的解决方案(不使用array_keys等方法来重复数组):
/**
* Array map alternative to work with values and keys of single array.
*
* Callable receives $value and $index of $sourceArray as arguments
* If keys are not preserved via $preserveKeys - $keyCallback can be used to determinate key
*
* @param array $sourceArray
* @param callable|null $valueCallback
* @param callable|null $keyCallback
* @param bool $preserveKeys
* @return array
*/
function array_map_indexed(
array $sourceArray,
?callable $valueCallback = null,
?callable $keyCallback = null,
bool $preserveKeys = true
): array {
$newArray = [];
foreach ($sourceArray as $key => $value) {
if ($preserveKeys) {
$newArray[$keyCallback ? $keyCallback($value, $key) : $key] = $valueCallback
? $valueCallback($value, $key)
: $value;
} else {
$newArray[] = $valueCallback
? $valueCallback($value, $key)
: $value;
}
}
return $newArray;
}
使用示例:
$result = array_map_indexed(
[
'a' => 'aValue',
'b' => 'bValue',
],
function($value, $index) {
return [$value, $index];
},
);
//Array ( [a] => Array ( [0] => aValue [1] => a ) [b] => Array ( [0] => bValue [1] => b ) )
$result = array_map_indexed(
[
'a' => 'aValue',
'b' => 'bValue',
],
function($value, $index) {
return $index.$value;
},
null,
false
);
//Array ( [0] => aaValue [1] => bbValue )
$result = array_map_indexed(
[
'a' => 'aValue',
'b' => 'bValue',
],
null,
function($value, $index) {
return $value === 'aValue' ? 'specificKey' : $index;
},
);
//Array ( [specificKey] => aValue [b] => bValue )
foreach
创建自己的映射函数:<?php
function myCallback($key, $val)
{
var_dump("myCallback - key: $key, val: $val");
return $val * 2;
}
function foreachMap($callback, $givenArray) {
$result = [];
foreach ($givenArray as $key=>$val) {
$result[$key] = $callback($key, $val);
}
return $result;
}
$values = array(4, 6, 3);
$mapped = foreachMap('myCallback', $values);
var_dump($mapped);
$values = array(4, 6, 3);
$mapped = array_map(function($v,$i) {return $v*2;}, $values, range(0,count($values)-1));
var_dump($mapped);
array_map()
提供任意数量的参数 :) - Aron Rotteveelarray_keys
返回的键与原始数组中的顺序相同。因此,您可能会将键映射到错误的值。安全的做法是仅将array_keys
作为array_map
的第二个参数,并使用use
语句将数组传递给闭包。 - user487772