Php array map key, $value

Here's my very simple, PHP 5.5-compatible solution:

function array_map_assoc(callable $f, array $a) {
    return array_column(array_map($f, array_keys($a), $a), 1, 0);
}

The callable you supply should itself return an array with two values, i.e. return [key, value]. The inner call to array_map therefore produces an array of arrays. This then gets converted back to a single-dimension array by array_column.

Usage

$ordinals = [
    'first' => '1st',
    'second' => '2nd',
    'third' => '3rd',
];

$func = function ($k, $v) {
    return ['new ' . $k, 'new ' . $v];
};

var_dump(array_map_assoc($func, $ordinals));

Output

array(3) {
  ["new first"]=>
  string(7) "new 1st"
  ["new second"]=>
  string(7) "new 2nd"
  ["new third"]=>
  string(7) "new 3rd"
}

Partial application

In case you need to use the function many times with different arrays but the same mapping function, you can do something called partial function application (related to ‘currying’), which allows you to only pass in the data array upon invocation:

function array_map_assoc_partial(callable $f) {
    return function (array $a) use ($f) {
        return array_column(array_map($f, array_keys($a), $a), 1, 0);
    };
}

...
$my_mapping = array_map_assoc_partial($func);
var_dump($my_mapping($ordinals));

Which produces the same output, given $func and $ordinals are as earlier.

NOTE: if your mapped function returns the same key for two different inputs, the value associated with the later key will win. Reverse the input array and output result of array_map_assoc to allow earlier keys to win. (The returned keys in my example cannot collide as they incorporate the key of the source array, which in turn must be unique.)


Alternative

Following is a variant of the above, which might prove more logical to some, but requires PHP 5.6:

function array_map_assoc(callable $f, array $a) {
    return array_merge(...array_map($f, array_keys($a), $a));
}

In this variant, your supplied function (over which the data array is mapped) should instead return an associative array with one row, i.e. return [key => value]. The result of mapping the callable is then simply unpacked and passed to array_merge. As earlier, returning a duplicate key will result in later values winning.

n.b. Alex83690 has noted in a comment that using array_replace here in the stead of array_merge would preserve integer keys. array_replace does not modify the input array, so is safe for functional code.

If you are on PHP 5.3 to 5.5, the following is equivalent. It uses array_reduce and the binary + array operator to convert the resulting two-dimensional array down to a one-dimensional array whilst preserving keys:

function array_map_assoc(callable $f, array $a) {
    return array_reduce(array_map($f, array_keys($a), $a), function (array $acc, array $a) {
        return $acc + $a;
    }, []);
}

Usage

Both of these variants would be used thus:

$ordinals = [
    'first' => '1st',
    'second' => '2nd',
    'third' => '3rd',
];

$func = function ($k, $v) {
    return ['new ' . $k => 'new ' . $v];
};

var_dump(array_map_assoc($func, $ordinals));

Note the => instead of , in $func.

The output is the same as before, and each can be partially applied in the same way as before.


 Summary

The goal of the original question is to make the invocation of the call as simple as possible, at the expense of having a more complicated function that gets invoked; especially, to have the ability to pass the data array in as a single argument, without splitting the keys and values. Using the function supplied at the start of this answer:

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

$array_map_assoc = function (callable $f, array $a) {
    return array_column(array_map($f, array_keys($a), $a), 1, 0);
};

$f = function ($key, $value) {
    return [$key, $key . ' loves ' . $value];
};

var_dump(array_values($array_map_assoc($f, $test_array)));

Or, for this question only, we can make a simplification to array_map_assoc() function that drops output keys, since the question does not ask for them:

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

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

$f = function ($key, $value) {
    return $key . ' loves ' . $value;
};

var_dump($array_map_assoc($f, $test_array));

So the answer is NO, you can't avoid calling array_keys, but you can abstract out the place where array_keys gets called into a higher-order function, which might be good enough.

Does array map preserve keys?

The returned array will preserve the keys of the array argument if and only if exactly one array is passed. If more than one array is passed, the returned array will have sequential integer keys.

What is PHP function Array_keys () used for?

The array_keys() is a built-in function in PHP and is used to return either all the keys of and array or the subset of the keys. Parameters: The function takes three parameters out of which one is mandatory and other two are optional.

What is the use of array_map in PHP?

The array_map() is an inbuilt function in PHP and it helps to modify all elements one or more arrays according to some user-defined condition in an easy manner. It basically, sends each of the elements of an array to a user-defined function and returns an array with new values as modified by that function.

What exactly do the Array_keys and Array_values functions do?

Array_keys() and array_values() are very closely related functions: the former returns an array of all the keys in an array, and the latter returns an array of all the values in an array.