@lexagl

Как отфильтровать по вложенной коллекции laravel?

Приветствую.
Есть коллекция типа
[
	[
		'name' => 'Alex',
		'lvl1' => ['count' => 5, 'min' => 12, 'max' => 5],
		'lvl2' => ['count' => 0, 'min' => 5, 'max' => 7],
		'lvl3' => ['count' => 18, 'min' => 0, 'max' => 8]
	],
	[
		'name' => 'Igor',
		'lvl1' => ['count' => 5, 'min' => 12, 'max' => 5],
		'lvl2' => ['count' => 0, 'min' => 5, 'max' => 7],
		'lvl3' => ['count' => 18, 'min' => 0, 'max' => 8]
	]
]

нужно удалить целиком элемент родителя если во вложенном среди count или min или max значение допустим 0?

Пробовал перед созданием коллекции проверять значения и заменять поле name на 0, а затем уже фильтровать, но это какой то shitOкод.

Подскажите пожалуйста как реализовать красиво?
  • Вопрос задан
  • 89 просмотров
Решения вопроса 1
alexey-m-ukolov
@alexey-m-ukolov Куратор тега PHP
Красиво у каждого своё, плюс оно зависит от нюансов проекта.
При условии, что мы не знаем заранее количество ключей lvlX, я бы написал так:
// Если нужно полностью удалить элемент, внутри которого есть хотя бы один нулевой lvl
array_filter(
    $a,
    function (array $item): bool {
        foreach ($item as $key => $value) {
            if (preg_match('~^lvl\d+$~', $key) === 1 && ($value['count'] === 0 || $value['min'] === 0 || $value['max'] === 0)) {
                return false;
            }
        }

        return true;
    }
);

// Если нужно удалять только сами нулевые lvl
array_map(
    function (array $item): array {
        return array_filter(
            $item,
            function ($value, string $key): bool {
                return preg_match('~^lvl\d+$~', $key) !== 1 || ($value['count'] !== 0 && $value['min'] !== 0 && $value['max'] !== 0);
            },
            ARRAY_FILTER_USE_BOTH
        );
    },
    $a
);

Код нужно адаптировать в зависимости от того, где там у вас реально коллекция, а где массив, но это уже тривиальная задача.
Ну и здесь предполагается, что структура каждого lvl фиксированная, то есть там всегда есть указанные ключи, чтобы не загромождать код проверками isset().

Ну а самое красивое, на мой вкус, переделать структуру на более адекватную:
[
    [
        'name' => 'Alex',
        'levels' => [
            ['index' => 1, 'count' => 5, 'min' => 12, 'max' => 5],
            ['index' => 2, 'count' => 0, 'min' => 5, 'max' => 7],
            ['index' => 3, 'count' => 18, 'min' => 0, 'max' => 8],
        ],
    ],
    [
        'name' => 'Igor',
        'levels' => [
            ['index' => 1, 'count' => 5, 'min' => 12, 'max' => 5],
            ['index' => 2, 'count' => 0, 'min' => 5, 'max' => 7],
            ['index' => 3, 'count' => 18, 'min' => 0, 'max' => 8],
        ],
    ]
];
Тогда и код фильтрации будет простым и понятным.

Если же ключи lvl1, lvl2 и lvl3 фиксированные, то, на мой вкус, лучше их захардкодить, это тоже значительно упростит жизнь в будущем, когда вы этот код откроете через пару лет и будете пытаться вспомнить что это за нагромождение из map, filter и регулярок.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы