@Lepilov

Фильтрация в списке словарей по динамическим критериям?

Есть функция принимающая на вход список словарей и фильтр в виде словаря (кол-во элементов в фильтре может меняться)
def filter_by(self, data: list, param: dict) -> list:
        for name, val in param.items():
            for index, el in enumerate(data):
                if el[name] != val:
                    data.pop(index)
        return data

Итерируемся по элементам словаря (фильтра) и внутри проходим по списку и отсеиваем если не совпадают значения в фильтре и в элементе списка. Но это плохая архитектура, так как удаление элементов из списка в процессе прохода по нему выглядит не лучшей идеей.

Как изменить кодфильтра для гарантированного удаления лишних элементов?
  • Вопрос задан
  • 209 просмотров
Решения вопроса 1
@deliro
Создать новый список и добавить туда элементы, которые подходят под предикат. Типичный map/filter/reduce

def filter_by(self, data: list, param: dict) -> list:
    result = []
    for el in data:
        matches = True
        for name, val in param.items():
            if el[name] != val:
                matches = False
                break
        if matches:
            result.append(el)
    return result


Или однострочником

def filter_by(self, data: list, param: dict) -> list:
    return [el for el in data if all(el[name] == val for name, val in param.items())]


rule of dumb: если метод/функция меняет свой аргумент, она не должна его возвращать (обычно это значит, что она вообще ничего не должна возвращать), имя метода/функции при этом должно явно говорить, что аргумент меняется (populate, remove_smth, drop_smth). Если метод/функция возвращает что-то, она не должна менять аргументы.

Но нужно понимать, что сложность создания нового списка — O(n) [при условии, что param достаточно мал и не растёт с увеличением data], а сложность выкидывания элементов по индексу — O(n**2) [потому что сложность операции .pop(idx) — O(n), в цикле по data — ещё O(n), итого O(n**2)]
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы