I see it's missing the obvious answer:
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;
}
Works exactly like array_map. Almost.
Actually, it's not pure map
as you know it from other languages. Php is very weird, so it requires some very weird user functions, for we don't want to unbreak our precisely broken worse is better
approach.
Really, it's not actually map
at all. Yet, it's still very useful.
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 unmap
py, 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:
null
is used as it's value WARNING:
Bear in mind, that this last feature is just a residue of previous features and it is probably completely useless. Relying on this feature is highly discouraged, as this feature is going to be randomly deprecated and changed unexpectedly in future releases.
NOTE:
Unlike in array_map
, all non-array parameters passed to array_map_assoc
, with the exception of first callback parameter, are silently casted to arrays.
EXAMPLES:
// TODO: examples, anyone?