有没有这样做的方法:

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

当前回答

我根据eis的答案做了这个函数:

function array_map_($callback, $arr) {
    if (!is_callable($callback))
        return $arr;

    $result = array_walk($arr, function(&$value, $key) use ($callback) {
        $value = call_user_func($callback, $key, $value);
    });

    if (!$result)
        return false;

    return $arr;
}

例子:

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

var_dump(array_map_(function($key, $value){
    return $key . " loves " . $value;
}, $arr));

输出:

array (
  'first_key' => 'first_key loves first_value,
  'second_key' => 'second_key loves second_value',
)

当然,您可以使用array_values来返回OP想要的内容。

array_values(array_map_(function($key, $value){
    return $key . " loves " . $value;
}, $test_array))

其他回答

YaLinqo库*非常适合这类任务。它是。net的LINQ的一个端口,完全支持所有回调中的值和键,类似于SQL。例如:

$mapped_array = from($test_array)
    ->select(function ($v, $k) { return "$k loves $v"; })
    ->toArray();

或者是:

$mapped_iterator = from($test_array)->select('"$k loves $v"');

这里,“$k爱$v”是这个库支持的完全闭包语法的快捷方式。最后的toArray()是可选的。方法链返回一个迭代器,因此如果结果只需要使用foreach迭代,则可以删除toArray调用。

*由我开发

如果你只需要它一次,闭包就可以了。我会用发电机。

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

$x_result = (function(array $arr) {
    foreach ($arr as $key => $value) {
        yield "$key loves $value";
    }
})($test_array);

var_dump(iterator_to_array($x_result));

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

对于可重复使用的东西:

function xmap(callable $cb, array $arr)
{
    foreach ($arr as $key => $value) {
        yield $cb($key, $value);
    }
}

var_dump(iterator_to_array(
    xmap(function($a, $b) { return "$a loves $b"; }, $test_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:例子,有人知道吗?

根据eis的回答,为了避免弄乱原始数组,我最终做了以下工作:

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

$result_array = array();
array_walk($test_array, 
           function($a, $b) use (&$result_array) 
           { $result_array[] = "$b loves $a"; }, 
           $result_array);
var_dump($result_array);

你可以使用map方法从这个数组库中轻松地实现你想要的:

Arr::map($test_array, function($a, $b) { return "$a loves $b"; });

此外,它保留键并返回新的数组,更不用说几个不同的模式来满足您的需求。