有没有这样做的方法:

$test_array = array(
    "first_key" => "first_value", 
    "second_key" => "second_value"
);

var_dump(
    array_map(
        function($a, $b) {
            return "$a loves $b";
        }, 
        array_keys($test_array), 
        array_values($test_array)
    )
);

但是不是调用array_keys和array_values,而是直接传递$test_array变量?

期望的输出是:

array(2) {
  [0]=>
  string(27) "first_key loves first_value"
  [1]=>
  string(29) "second_key loves second_value"
}

当前回答

我一直喜欢数组映射的javascript变体。最简单的版本是:

/**
 * @param  array    $array
 * @param  callable $callback
 * @return array
 */
function arrayMap(array $array, callable $callback)
{
    $newArray = [];

    foreach( $array as $key => $value )
    {
        $newArray[] = call_user_func($callback, $value, $key, $array);
    }

    return $newArray;
}

现在你可以给它一个回调函数如何构造值。

$testArray = [
    "first_key" => "first_value", 
    "second_key" => "second_value"
];

var_dump(
    arrayMap($testArray, function($value, $key) {
        return $key . ' loves ' . $value;
    });
);

其他回答

我所说的“手动循环”是指编写一个使用foreach的自定义函数。它像array_map一样返回一个新数组,因为函数的作用域导致$array是一个复制,而不是一个引用:

function map($array, callable $fn) {
  foreach ($array as $k => &$v) $v = call_user_func($fn, $k, $v);
  return $array;
}

你使用array_map和array_keys的技术实际上看起来更简单,也更强大,因为你可以使用null作为回调来返回键值对:

function map($array, callable $fn = null) {
  return array_map($fn, array_keys($array), $array);
}

我发现它忽略了最明显的答案:

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

工作方式完全类似于array_map。几乎。

实际上,它不是纯粹的地图,就像你从其他语言中知道的那样。Php非常奇怪,所以它需要一些非常奇怪的用户函数,因为我们不想恢复我们精确地破坏越坏越好的方法。

实际上,它根本不是地图。然而,它仍然非常有用。

First obvious difference from array_map, is that the callback takes outputs of each() from every input array instead of value alone. You can still iterate through more arrays at once. Second difference is the way the key is handled after it's returned from callback; the return value from callback function should be array('new_key', 'new_value'). Keys can and will be changed, same keys can even cause previous value being overwritten, if same key was returned. This is not common map behavior, yet it allows you to rewrite keys. Third weird thing is, if you omit key in return value (either by array(1 => 'value') or array(null, 'value')), new key is going to be assigned, as if $array[] = $value was used. That isn't map's common behavior either, yet it comes handy sometimes, I guess. Fourth weird thing is, if callback function doesn't return a value, or returns null, the whole set of current keys and values is omitted from the output, it's simply skipped. This feature is totally unmappy, yet it would make this function excellent stunt double for array_filter_assoc, if there was such function. If you omit second element (1 => ...) (the value part) in callback's return, null is used instead of real value. Any other elements except those with keys 0 and 1 in callback's return are ignored. And finally, if lambda returns any value except of null or array, it's treated as if both key and value were omitted, so: new key for element is assigned null is used as it's value

警告: 请记住,最后一个功能只是前面功能的残留,它可能完全无用。非常不鼓励依赖这个特性,因为在未来的版本中,这个特性将被随机弃用并意外地更改。

注意: 与array_map不同,传递给array_map_assoc的所有非数组参数(第一个回调参数除外)都被无声地强制转换为数组。

例子: // TODO:例子,有人知道吗?

我一直喜欢数组映射的javascript变体。最简单的版本是:

/**
 * @param  array    $array
 * @param  callable $callback
 * @return array
 */
function arrayMap(array $array, callable $callback)
{
    $newArray = [];

    foreach( $array as $key => $value )
    {
        $newArray[] = call_user_func($callback, $value, $key, $array);
    }

    return $newArray;
}

现在你可以给它一个回调函数如何构造值。

$testArray = [
    "first_key" => "first_value", 
    "second_key" => "second_value"
];

var_dump(
    arrayMap($testArray, function($value, $key) {
        return $key . ' loves ' . $value;
    });
);

我将使用5.6或更高版本为该问题添加另一个解决方案。不知道它是否比已经很棒的解决方案更有效(可能不是),但对我来说,它只是更容易阅读:

$myArray = [
    "key0" => 0,
    "key1" => 1,
    "key2" => 2
];

array_combine(
    array_keys($myArray),
    array_map(
        function ($intVal) {
            return strval($intVal);
        },
        $myArray
    )
);

使用strval()作为array_map中的示例函数,这将生成:

array(3) {
  ["key0"]=>
  string(1) "0"
  ["key1"]=>
  string(1) "1"
  ["key2"]=>
  string(1) "2"
}

希望我不是唯一一个觉得这个很容易理解的人。 Array_combine从一个键数组和一个值数组中创建了一个key =>值数组,剩下的是不言自明的。

看过来!有一个简单的解决方案!

function array_map2(callable $f, array $a)
{
    return array_map($f, array_keys($a), $a);
}

正如问题中所述,array_map已经具备所需的功能。这里的其他答案严重地把事情复杂化了:array_walk不是函数式的。

使用

正如你从例子中所期望的那样:

$test_array = array("first_key" => "first_value", 
                    "second_key" => "second_value");

var_dump(array_map2(function($a, $b) { return "$a loves $b"; }, $test_array));