Есть ли способ сделать что-то вроде этого:
$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"
}
php
functional-programming
Хосе Томас Тосино
источник
источник
Ответы:
Не с array_map, так как он не обрабатывает ключи.
array_walk делает:
Однако он меняет массив, заданный в качестве параметра, поэтому это не совсем функциональное программирование (так как у вас есть вопрос, помеченный так). Кроме того, как указано в комментарии, это только изменит значения массива, поэтому ключи не будут такими, как вы указали в вопросе.
Вы можете написать функцию, которая исправляет точки над собой, если хотите, например:
источник
$a = "$b loves $a"
, чтобы соответствовать желаемому выходу OP.array_walk()
как не возвращает результирующий массив, а вместо этого bool.Это, наверное, самый короткий и простой способ рассуждать о:
источник
array_keys()
. Хотя это кажется глупым требованием.Вот мое очень простое, PHP 5.5-совместимое решение:
Вызываемый объект должен сам возвращать массив с двумя значениями, т.е.
return [key, value]
. Внутренний вызов,array_map
следовательно, создает массив массивов. Затем он преобразуется обратно в одномерный массивarray_column
.использование
Вывод
Частичное применение
Если вам нужно многократно использовать функцию с разными массивами, но с одной и той же функцией отображения, вы можете сделать то, что называется частичным применением функции (связано с « каррированием »), что позволяет передавать массив данных только при вызове:
Который производит такой же результат, учитывая
$func
и$ordinals
являются такими , как раньше.ПРИМЕЧАНИЕ: если ваша отображенная функция возвращает одну и ту же клавишу для двух разных входов, победит значение, связанное с более поздней клавишей. Обратный входной массив и выходной результат
array_map_assoc
позволяют более ранним ключам выиграть. (Возвращенные ключи в моем примере не могут конфликтовать, поскольку они включают ключ исходного массива, который, в свою очередь, должен быть уникальным.)альтернатива
Ниже приведен вариант выше, который может оказаться более логичным для некоторых, но требует PHP 5.6:
В этом варианте, ваша функция , применяемая (над которой массив данных отображается) вместо этого следует возвращать ассоциативный массив с одной строкой, то есть
return [key => value]
. Результат сопоставления вызываемого объекта затем просто распаковывается и передаетсяarray_merge
. Как и ранее, возврат дублирующего ключа приведет к выигрышу более поздних значений.Если вы используете PHP 5.3 до 5.5, следующее эквивалентно. Он использует
array_reduce
и+
оператор двоичного массива для преобразования результирующего двумерного массива в одномерный массив с сохранением ключей:использование
Оба эти варианта будут использоваться таким образом:
Обратите внимание , что
=>
вместо того , чтобы,
в$func
.Вывод такой же, как и раньше, и каждый может быть частично применен так же, как и раньше.
Резюме
Цель исходного вопроса - сделать вызов как можно более простым, за счет наличия более сложной функции, которая вызывается; особенно, чтобы иметь возможность передавать массив данных как один аргумент, не разделяя ключи и значения. Используя функцию, указанную в начале этого ответа:
Или, только для этого вопроса, мы можем упростить
array_map_assoc()
функцию, которая отбрасывает выходные клавиши, поскольку вопрос не задает их:Таким образом, ответ НЕТ , вы не можете избежать вызова
array_keys
, но вы можете абстрагироваться от места, где вызываетсяarray_keys
функция более высокого порядка, что может быть достаточно хорошим.источник
array_merge
на,array_replace
чтобы сохранить ключи, которые были бы целыми числами.С PHP5.3 или новее:
источник
Вот как я реализовал это в своем проекте.
источник
Смотри сюда! Есть тривиальное решение!
Как указано в вопросе,
array_map
уже есть именно требуемая функциональность . Другие ответы здесь серьезно усложняют вещи:array_walk
это не функционально.использование
Точно так же, как и следовало ожидать от вашего примера:
источник
qrrqy_keys()
вопрос не должен использоваться для #reasonsПод «ручным циклом» я подразумевал написание пользовательской функции, которая использует
foreach
. Это возвращает новый массив, как этоarray_map
происходит, потому что область действия функции$array
является копией, а не ссылкой:Ваша техника использования
array_map
witharray_keys
хотя на самом деле кажется более простой и более мощной, потому что вы можете использоватьnull
в качестве обратного вызова для возврата пар ключ-значение:источник
unset( $value )
потому что оно все еще существует в определенной области.Основываясь на ответе eis , вот что я в итоге сделал, чтобы не испортить исходный массив:
источник
array_walk
как вы не ссылаетесь на него в закрытии.Я сделал эту функцию, основываясь на ответе EIS :
Пример:
Вывод:
Конечно, вы можете использовать,
array_values
чтобы вернуть именно то, что хочет ОП.источник
$arr
тип массив, однако, если вы введете подсказку в качестве аргумента как,callable
иarray
вместо этого вы можете отбросить проверкуis_callable
. Затем вы делаете присвоение $ value, которое затем не используется. Вы должны просто игнорировать возвращаемое значение. В-третьих, было бы лучше вызвать исключение в обратном вызове, чем возвращать false. Затем вы либо всегда вернете правильное значение, либо всегда выбросите.Библиотека YaLinqo * хорошо подходит для такого рода задач. Это порт LINQ из .NET, который полностью поддерживает значения и ключи во всех обратных вызовах и напоминает SQL. Например:
или просто:
Вот
'"$k loves $v"'
ярлык для полного синтаксиса закрытия, который поддерживает эта библиотека.toArray()
в конце не обязательно. Цепочка методов возвращает итератор, поэтому, если нужно просто повторить результат с помощьюforeach
,toArray
вызов может быть удален.* разработано мной
источник
Я бы сделал что-то вроде этого:
Полученные результаты:
источник
Я добавлю еще одно решение проблемы, используя версию 5.6 или более позднюю. Не знаю, эффективнее ли это, чем и без того отличные решения (возможно, нет), но для меня это проще читать:
Используя
strval()
в качестве примера функцию вarray_map
, это сгенерирует:Надеюсь, я не единственный, кто находит это довольно простым для понимания.
array_combine
создаетkey => value
массив из массива ключей и массива значений, остальное довольно очевидно.источник
Вы можете использовать метод map из этой библиотеки массивов для достижения именно того, что вы хотите, так же легко, как:
также он сохраняет ключи и возвращает новый массив, не говоря уже о нескольких различных режимах, которые соответствуют вашим потребностям.
источник
Источник
источник
Мне всегда нравится javascript-вариант массива map. Самый простой вариант этого будет:
Так что теперь вы можете просто передать ему функцию обратного вызова, как построить значения.
источник
h(g(f($data)))
применяетсяf
, затемg
, затемh
к вашему данные. Обычно считается, что в функциональном программировании более универсально иметь функцию, которая выполняет ту же самую операцию с данными о дайверах, чем иметь функцию, которая применяет функции дайверов к фиксированному набору данных.Другой способ сделать это с (без) сохранением ключей:
источник
Я вижу, что отсутствует очевидный ответ:
Работает точно так же, как array_map. Почти.
На самом деле, это не чисто,
map
как вы знаете это из других языков. Php очень странный, поэтому он требует некоторых очень странных пользовательских функций, потому что мы не хотим разбивать наши точно сломанныеworse is better
подход.На самом деле, это не
map
совсем так. Тем не менее, это все еще очень полезно.Первое очевидное отличие от array_map состоит в том, что обратный вызов получает выходные данные
each()
из каждого входного массива вместо одного значения. Вы все еще можете перебирать больше массивов одновременно.Второе отличие - это способ обработки ключа после его возврата из обратного вызова; возвращаемое значение из функции обратного вызова должно быть
array('new_key', 'new_value')
. Ключи могут и будут изменены, эти же ключи могут даже привести к перезаписи предыдущего значения, если тот же ключ был возвращен. Это не обычноеmap
поведение, но оно позволяет перезаписывать ключи.Третья странная вещь - если вы опускаете
key
возвращаемое значение (либо by,array(1 => 'value')
либоarray(null, 'value')
), новый ключ будет назначен, как если бы он$array[] = $value
был использован. Это неmap
обычное поведение, но иногда бывает полезно, я думаю.Четвертая странная вещь: если функция обратного вызова не возвращает значение или возвращает
null
, весь набор текущих ключей и значений опускается в выводе, он просто пропускается. Эта функция совершенно не работаетmap
, но это сделало бы эту функцию отличным трюком для двойнойarray_filter_assoc
, если бы была такая функция.Если вы опустите второй элемент (
1 => ...
) ( часть значения ) в возврате обратного вызова,null
используется вместо реального значения.Любые другие элементы, кроме тех, которые имеют ключи
0
и1
возвращаются в обратном вызове, игнорируются.И, наконец, если лямбда возвращает какое-либо значение, кроме
null
массива или, оно обрабатывается так, как если бы ключ и значение были опущены, поэтому:null
используется как значениеПРИМЕЧАНИЕ.
В отличие от in
array_map
, всеarray_map_assoc
параметры, не являющиеся массивами, переданные , за исключением первого параметра обратного вызова, автоматически преобразуются в массивы.ПРИМЕРЫ:
// TODO: examples, anyone?
источник