В чем именно разница array_map
, array_walk
и array_filter
. Из документации видно, что вы можете передать функцию обратного вызова для выполнения действия над предоставленным массивом. Но я не вижу особой разницы между ними.
Они выполняют то же самое?
Могут ли они быть взаимозаменяемыми?
Буду признателен за помощь с иллюстративным примером, если они вообще отличаются.
Ответы:
array_map
не может изменить значения внутри входных массивов, покаarray_walk
can; в частности,array_map
никогда не меняет своих аргументов.array_map
не может работать с ключами массива,array_walk
может.array_map
возвращает новый массив,array_walk
только возвращаетtrue
. Следовательно, если вы не хотите создавать массив в результате обхода одного массива, вы должны использоватьarray_walk
.array_map
также может принимать произвольное количество массивов и может итерировать их параллельно,array_walk
работая только с одним.array_walk
может получить дополнительный произвольный параметр для передачи в обратный вызов. Это в основном не имеет отношения к PHP 5.3 (когда были введены анонимные функции ).array_map
имеет ту же длину, что и самый большой входной массив;array_walk
не возвращает массив, но в то же время не может изменять количество элементов исходного массива;array_filter
выбирает только подмножество элементов массива в соответствии с функцией фильтрации. Это сохраняет ключи.Пример:
Результат:
источник
array_map(callback($key, $value), array_keys($array), $array)
Идея отображения функции в массив данных происходит из функционального программирования. Вы не должны думать о том,
array_map
какforeach
цикл , который вызывает функцию для каждого элемента массива (несмотря на то, что, как это реализовано). Это следует рассматривать как применение функции к каждому элементу в массиве независимо.Теоретически такие вещи, как отображение функций, могут выполняться параллельно, поскольку функция, применяемая к данным, должна влиять ТОЛЬКО на данные, а НЕ на глобальное состояние. Это потому, что
array_map
можно было выбрать любой порядок применения функции к элементам (даже если в PHP это не так).array_walk
с другой стороны это совершенно противоположный подход к обработке массивов данных. Вместо того, чтобы обрабатывать каждый элемент отдельно, он использует состояние (&$userdata
) и может редактировать элемент на месте (подобно циклу foreach). Поскольку каждый раз, когда элемент$funcname
применяется к нему, он может изменять глобальное состояние программы и поэтому требует единого правильного способа обработки элементов.Вернемся к PHP
array_map
иarray_walk
практически идентичны, за исключением того, чтоarray_walk
дают вам больший контроль над итерацией данных и обычно используются для «изменения» данных на месте по сравнению с возвратом нового «измененного» массива.array_filter
это действительно приложениеarray_walk
(илиarray_reduce
), и оно более или менее просто для удобства.источник
array_filter()
можно реализовать с помощьюarray_walk()
?Из документации,
array_walk принимает массив и функцию
F
и модифицирует их, заменяя каждый элемент x наF(x)
.array_map делает то же самое, за исключением того, что вместо модификации на месте он возвращает новый массив с преобразованными элементами.
array_filter с функцией
F
, вместо преобразования элементов, удалит все элементы, для которыхF(x)
это не такисточник
array_walk
вернул массив вродеarray_map
и понял, что проблема в моей функции. До тех пор, пока я не увидел это, я не понял, что тип возвращаемого значения является логическим.Другие ответы достаточно хорошо демонстрируют разницу между array_walk (модификация на месте) и array_map (вернуть измененную копию). Тем не менее, они на самом деле не упоминают array_reduce, которая является отличным способом понять array_map и array_filter.
Функция array_reduce принимает массив, функцию с двумя аргументами и «аккумулятор», например:
Элементы массива объединяются с аккумулятором по одному, используя данную функцию. Результат вышеприведенного вызова такой же, как при выполнении этого:
Если вы предпочитаете думать с точки зрения циклов, это все равно что делать следующее (я фактически использовал это как запасной вариант, когда array_reduce не был доступен):
Эта циклическая версия проясняет, почему я назвал третий аргумент «аккумулятором»: мы можем использовать его для накопления результатов на каждой итерации.
Так что же это нужно делать с array_map и array_filter? Оказывается, они оба особого вида array_reduce. Мы можем реализовать их так:
Не обращайте внимания на тот факт, что array_map и array_filter принимают свои аргументы в другом порядке; это просто еще одна особенность PHP. Важным моментом является то, что правая часть идентична, за исключением функций, которые я назвал $ MAP и $ FILTER. Итак, как они выглядят?
Как видите, обе функции берут $ аккумулятор и возвращают его снова. Есть два различия в этих функциях:
Обратите внимание, что это далеко не бесполезные мелочи; мы можем использовать его, чтобы сделать наши алгоритмы более эффективными!
Мы часто видим код, подобный этим двум примерам:
Использование array_map и array_filter вместо циклов делает эти примеры довольно привлекательными. Однако это может быть очень неэффективно, если $ input велико, так как первый вызов (map или filter) будет проходить по $ input и создавать промежуточный массив. Этот промежуточный массив передается прямо во второй вызов, который снова будет проходить через все это, затем промежуточный массив нужно будет собрать мусором.
Мы можем избавиться от этого промежуточного массива, используя тот факт, что array_map и array_filter являются примерами array_reduce. Объединив их, нам нужно пройти через входные данные только один раз в каждом примере:
ПРИМЕЧАНИЕ. Мои реализации array_map и array_filter выше не будут вести себя точно так же, как PHP, поскольку мой array_map может обрабатывать только один массив за раз, а мой array_filter не будет использовать «empty» в качестве функции $ по умолчанию. Также ни один из них не сохранит ключи.
Не трудно заставить их вести себя как PHP, но я чувствовал, что эти сложности затруднят выявление основной идеи.
источник
В следующей редакции делается попытка более четко разграничить PHP-функции array_filer (), array_map () и array_walk (), которые происходят из функционального программирования:
array_filter () отфильтровывает данные, создавая в результате новый массив, содержащий только нужные элементы предыдущего массива, следующим образом:
живой код здесь
Все числовые значения отфильтрованы из массива $, в результате чего $ фильтруется только с фруктами.
array_map () также создает новый массив, но в отличие от array_filter () результирующий массив содержит каждый элемент входного $ фильтрованного, но с измененными значениями, благодаря применению обратного вызова к каждому элементу следующим образом:
живой код здесь
Код в этом случае применяет обратный вызов, используя встроенную функцию strtoupper (), но пользовательская функция также является еще одним приемлемым вариантом. Обратный вызов применяется к каждому элементу $ отфильтрованного и тем самым порождает $ nu, элементы которого содержат значения в верхнем регистре.
В следующем фрагменте массив walk () обходит $ nu и вносит изменения в каждый элемент в отношении оператора ссылки '&'. Изменения происходят без создания дополнительного массива. Значение каждого элемента меняется на место в более информативную строку с указанием его ключа, категории и значения.
Посмотреть демо
Примечание: функция обратного вызова относительно array_walk () принимает два параметра, которые автоматически получают значение элемента и его ключ, и в этом порядке, также при вызове array_walk (). (Смотрите больше здесь ).
источник
$lambda
и$callback
являются просто eta-расширениями существующих функций и, следовательно, являются полностью избыточными. Вы можете получить тот же результат, передав (имя) основную функцию:$filtered = array_filter($array, 'ctype_alpha');
и$nu = array_map('strtoupper', $filtered);