Как использовать array_reduce в неизменном стиле?

До этого момента я проходил онлайн-обучение на ресурсе, который мне очень нравился. Проблема в том, что они хотят, чтобы моя отлично работающая функция 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 "в неизменяемом стиле"...

Чтобы не менять ввод (и акк?!), вам следует изменить свою строку на $accNew = array_merge($accNew, $newValue);

IT goldman 18.11.2022 20:43

Как изменить акк, используя его в операции array_merge? Мне кажется, что это не меняется... И уведомление относится к $accNew[] = $newValue; также линия, где оригинальный акк вообще не используется...

Artem Pokhiliuk 19.11.2022 06:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
2
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не уверен на 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;

Artem Pokhiliuk 19.11.2022 06:39

@ArtemPokhiliuk, да, подумав об этом, я обновил его, чтобы объединить все. С точки зрения производительности временная переменная может быть более оптимальной.

Chris Haas 19.11.2022 15:22

Эй, мужик! Большое спасибо, все работает, проходит этот дурацкий тест! Никогда не забуду вас, потому что вы ответили на мой самый первый вопрос здесь, и я собираюсь осветить его в программировании в ближайшие годы)) Хотя не совсем понял, в чем разница с точки зрения смены оригинального аккумулятора между вашей версией и моя вторая версия. Они оба кажутся мне не изменяющими его. С удовольствием разобрался бы, потому что у меня в проекте еще много похожих заметок и я не хочу каждый раз задавать здесь вопросы...

Artem Pokhiliuk 19.11.2022 16:18

Это всего лишь предположение, но если вы полностью проигнорируете array_reduce и просто посмотрите на функцию, вы измените один из предоставленных параметров. Для этого конкретного случая это не имеет значения, но в будущем может наступить день с другой функцией, где это вас укусит. «Я передал CHEESE функции, но она продолжает говорить Cheese». Или вы случайно делаете if ($var = true) вместо ===.

Chris Haas 19.11.2022 16:51

Другие вопросы по теме