Вот мое очень простое, PHP 5.5-совместимое решение:
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
Вызываемый объект должен сам возвращать массив с двумя значениями, т.е. return [key, value]
. Внутренний вызов, array_map
следовательно, создает массив массивов. Затем он преобразуется обратно в одномерный массив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
являются такими , как раньше.
ПРИМЕЧАНИЕ: если ваша отображенная функция возвращает одну и ту же клавишу для двух разных входов, победит значение, связанное с более поздней клавишей. Обратный входной массив и выходной результат array_map_assoc
позволяют более ранним ключам выиграть. (Возвращенные ключи в моем примере не могут конфликтовать, поскольку они включают ключ исходного массива, который, в свою очередь, должен быть уникальным.)
альтернатива
Ниже приведен вариант выше, который может оказаться более логичным для некоторых, но требует PHP 5.6:
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
В этом варианте, ваша функция , применяемая (над которой массив данных отображается) вместо этого следует возвращать ассоциативный массив с одной строкой, то есть 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));
Таким образом, ответ НЕТ , вы не можете избежать вызова array_keys
, но вы можете абстрагироваться от места, где вызывается array_keys
функция более высокого порядка, что может быть достаточно хорошим.