これが私の非常にシンプルなPHP 5.5互換のソリューションです。
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
指定する呼び出し可能オブジェクトは、それ自体が2つの値を持つ配列を返す必要がありますreturn [key, value]
。array_map
したがって、への内部呼び出しにより、配列の配列が生成されます。次に、これはによって1次元配列に変換されarray_column
ます。
使用法
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k, 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
出力
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
部分適用
異なる配列で同じマッピング関数を何度も使用する必要がある場合は、部分的な関数の適用(「カリー化」に関連)を実行できます。これにより、呼び出し時にデータ配列のみを渡すことができます。
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));
与えられ$func
、$ordinals
以前と同じ出力を生成します。
注:マップされた関数が2つの異なる入力に対して同じキーを返す場合、後のキーに関連付けられた値が優先されます。入力配列と出力結果を逆にarray_map_assoc
して、以前のキーが勝つようにします。(私の例で返されたキーは、ソース配列のキーを組み込んでいるため、衝突することができません。ソース配列は一意でなければなりません。)
オルタナティブ
以下は上記のバリエーションで、一部の人にとってはより論理的である可能性がありますが、PHP 5.6が必要です。
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
このバリアントでは、提供された関数(データ配列がマップされている関数)は、代わりに1行の連想配列(つまり)を返す必要がありreturn [key => value]
ます。呼び出し可能オブジェクトをマッピングした結果は、単純に解凍されてに渡されarray_merge
ます。以前と同様に、重複したキーを返すと、後の値が優先されます。
nb Alex83690はコメントのarray_replace
中で、の代わりにここで使用するとarray_merge
整数キーが保持されることを指摘しています。array_replace
入力配列は変更されないため、関数型コードに対して安全です。
PHP 5.3から5.5を使用している場合、以下は同等です。これは、使用array_reduce
バイナリ+
キーを保持しながら、一次元アレイに得られた二次元アレイダウンを変換する配列演算子:
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;
}, []);
}
使用法
これらのバリアントはどちらもこのように使用されます。
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k => 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
なお、=>
代わりの,
の中で$func
。
出力は以前と同じで、それぞれを以前と同じ方法で部分的に適用できます。
概要
元の質問の目的は、呼び出される呼び出しがより複雑になる代わりに、呼び出しの呼び出しをできるだけ簡単にすることです。特に、キーと値を分割せずに、データ配列を単一の引数として渡す機能があります。この回答の冒頭で提供されている関数を使用します。
$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)));
または、この質問についてのみ、array_map_assoc()
質問がそれらを要求しないため、出力キーを削除する機能を簡略化できます。
$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));
したがって、答えはNOです。呼び出しを回避することはできませんが、呼び出されるarray_keys
場所をarray_keys
より高次の関数に抽象化できます。これで十分でしょう。