До этого момента я проходил онлайн-обучение на ресурсе, который мне очень нравился.
Проблема в том, что они хотят, чтобы моя отлично работающая функция array_reduce
была написана «в неизменном стиле». А значит внутри ничего не должно мутировать, даже аккумулятор. Что мне кажется бессмысленным.
Итак, вот фрагмент кода, который я использую в том учебном проекте, который они не хотят принимать, функция для выравнивания массива:
function flatten(array $tree)
{
$result = array_reduce($tree, function ($acc, $item) {
$newValue = is_array($item) ? flatten($item) : $item;
if (!is_array($newValue)) {
$acc[] = $newValue;
} else {
$acc = array_merge($acc, $newValue);
}
return $acc;
}, []);
return $result;
}
Он работает отлично, но этот ресурс (не бесплатный, кстати) не принимает его с уведомлениями «Не следует использовать мутирующие операторы» в строках, где я меняю $acc.
Так что я спрашиваю их WTF, и они мне отвечают: не меняйте входной аргумент, а вместо этого сделайте новый акк и верните этот новый акк из обратного вызова. Поэтому я переписываю так:
function flatten(array $tree)
{
$result = array_reduce($tree, function ($acc, $item) {
$accNew = $acc;
$newValue = is_array($item) ? flatten($item) : $item;
if (!is_array($newValue)) {
$accNew[] = $newValue;
} else {
$accNew = array_merge($acc, $newValue);
}
return $accNew;
}, []);
return $result;
}
Но это не помогает, тот же «Не следует использовать мутирующие операторы» замечает для строк, где сейчас изменяется $accNew.
Что за черт? Я совершенно сбит с толку. Это вообще имеет смысл? Это адекватное требование? Потому что я погуглил, и кажется, что в Интернете почти нет людей, которые были бы заинтересованы в использовании array_reduce
"в неизменяемом стиле"...
Как изменить акк, используя его в операции array_merge? Мне кажется, что это не меняется... И уведомление относится к $accNew[] = $newValue; также линия, где оригинальный акк вообще не используется...
Я не уверен на 100%, как этот код используется, но я думаю, что вы даже можете полностью пропустить запись в аккумулятор или его копию, а вместо этого просто return
:
function flatten(array $tree): array
{
return array_reduce(
$tree,
static function ($acc, $item) {
$newValue = is_array($item) ? flatten($item) : $item;
return array_merge($acc, is_array($newValue) ? $newValue : [$newValue]);
},
[]
);
}
Редактировать: мой предыдущий ответ не учитывал предыдущие элементы в аккумуляторе, это учитывает.
Не работает, потому что (как мне кажется) return [$newValue];
не является корректной заменой $accNew[] = $newValue; return $accNew;
@ArtemPokhiliuk, да, подумав об этом, я обновил его, чтобы объединить все. С точки зрения производительности временная переменная может быть более оптимальной.
Эй, мужик! Большое спасибо, все работает, проходит этот дурацкий тест! Никогда не забуду вас, потому что вы ответили на мой самый первый вопрос здесь, и я собираюсь осветить его в программировании в ближайшие годы)) Хотя не совсем понял, в чем разница с точки зрения смены оригинального аккумулятора между вашей версией и моя вторая версия. Они оба кажутся мне не изменяющими его. С удовольствием разобрался бы, потому что у меня в проекте еще много похожих заметок и я не хочу каждый раз задавать здесь вопросы...
Это всего лишь предположение, но если вы полностью проигнорируете array_reduce
и просто посмотрите на функцию, вы измените один из предоставленных параметров. Для этого конкретного случая это не имеет значения, но в будущем может наступить день с другой функцией, где это вас укусит. «Я передал CHEESE
функции, но она продолжает говорить Cheese
». Или вы случайно делаете if ($var = true)
вместо ===
.
Чтобы не менять ввод (и акк?!), вам следует изменить свою строку на
$accNew = array_merge($accNew, $newValue);