PHP: array_map и ключи массива

09 Jun 2016

Интересно, почему такой вопрос часто всплывает на форумах или где-то еще?

Сначала постараюсь ответить на вопрос “нафига?”, а потом на вопрос “как?”.

Мы привыкли, что в в питоне, js и множестве других языков и фреймворков есть функция map, которая применяет некоторую функцию-обработчик к каждому элементу в списке данных и возвращающую результат в том же порядке. Пруф.

Но никто не ждал, что хеш-таблица и массив в контексте одного из языков будет означать одно и то же. Опять же пруф.

Этот постыдный момент из жизни структуры привел к тому, что одним из самых частых применений массивов (в пхп конечно же) стало создание отображений категория=>какое-то значение.

А после того как у вас появилось отображение вы, вероятно, захотите это где-нибудь на сгенерированной странице отобразить.

Т.е. показать пользователю сам параметр, а скобках его категорию.

Как мы делаем это в языках (фреймворках), которые разделяют понятие массива и хеш-таблицы? Перебираем объект, который содержит категории и формируем по нему массив выводимых данных. Наверное так.

И тут мы открываем руководство по php и видим, что она применяет некий колбек ко всем элементам массива и после этого возвращает новый массив.

Удобно же! Применили колбек к массиву и получили обработанный.

$array = [  
 'category1' =\> 'first category',  
 'category2' =\> 'second category',  
];

var\_dump(array\_map(function(....

И что-то не заладилось. :) Ключи в колбек не попадают. Можно сделать все через foreach, но тогда нам потребуется еще одна переменная. А тут все было просто и наглядно.

И мы идем в гугель: “php array_map with keys”.

А зачем гуглить-то?

$array = [  
 'category1' =\> 'first category',  
 'category2' =\> 'second category',  
];

var\_dump(array\_map(function($key, $value) {  
 return "{$key} =\> {$value}";  
}, array\_keys($array), $array));

И все отлично работает. И притом правильно. Относительно конечно же. И никаких вам лишних переменных.

А тем временем в коде вновь и вновь появляются конструкции вида

$array = [  
 'category1' =\> 'first category',  
 'category2' =\> 'second category',  
];

$description = [];

foreach ($array as $key =\> $value) {  
 $description[] = "{$key} =\> {$value}";  
}

Или еще хуже.

$array = [  
 'category1' =\> 'first category',  
 'category2' =\> 'second category',  
];

$description = [];

array\_walk($array, function($value, $key) {  
 $description[] = "{$key} =\> {$value}";  
});

Проблема кейса из статьи может быть и раздута, но при вчитывании в сотни строк кода более-менее понятными сходу являются только первые два варианта.

Вариант же с array_walk на понятность никак не претендует (как и решение подобной задачи при помощи .each в jquery).