Функция Python для фильтрации данных из массива

Я сделал функцию для цикла по массиву и фильтрации результатов.

def filter_data(data, match_d=None, trim_matches=False):
    result_matches = {}  # stores matched
    result_unmatches = {}  # stores not matched

    # loop every record in data
    for key, value in data.items():

        # match record with filter criteria
        for search_string, search_key_name in match_d.items():

            if search_string == value[search_key_name]:
                result_matches[key] = value
            else:
                result_unmatches[key] = value

    if trim_matches is False:  # return only matches
        return result_matches
    else:  # return all but matches
        return result_unmatches



data_dict = {0: {'name': 'one'},
             1: {'name': 'two'},
             2: {'name': 'three'},
             3: {'name': 'four'},
             4: {'name': 'five'}}

result = filter_data(data_dict,
                     match_d = {'one': 'name', 'two': 'name'},
                     trim_matches=True)

print(result)

#returns: {0: {'name': 'one'}, 1: {'name': 'two'}, 2: {'name': 'three'}, 3: {'name': 'four'}, 4: {'name': 'five'}}

#expected {2: {'name': 'three'}, 3: {'name': 'four'}, 4: {'name': 'five'}}

Когда я использую trim_matches=False при вызове функции, он работает так, как ожидалось, однако когда я использую trim_matches=True, это не так.

Причина в том, что он повторяет ключ через каждое совпадение, а затем записывает в оба списка result_matches и result_unmatches, однако я не могу найти простое решение этой проблемы.

Я мог бы просто написать result_matches, затем сравнить data и удалить совпадения из данных при использовании trim_matches=True, но я не хочу добавлять дополнительный код для функции.

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

Альтернативное решение: переписать полный функциональный код и логику, но кода должно быть меньше, чем используется в настоящее время.

Нет, разрешен только чистый Python.

Редактировать: понимая, что отладка трудна, я пошел дальше, раскрасил и расположил вывод, теперь легко увидеть, что происходит.

Установите дополнительную переменную перед внутренним циклом for, например. г. matched = False. Если вы нашли совпадение, установите его True. После внутреннего цикла for добавьте запись в result_unmatches, если переменная все еще равна False.

Michael Butscher 23.02.2024 11:53

@MichaelButscher, здорово, это сработало! я пробовал что-то подобное, но меня раздражала сложность функции и сложность предоставленных данных, я упростил ее только перед публикацией в StackOverflow, думаю, в следующий раз мне не стоит быть таким ленивым и сделать простую версию функции для поиска простое решение. Не понял, что второй цикл выполняет только сравнение с фильтром, присвоение не обязательно должно происходить внутри второго цикла.

Roman Toasov 23.02.2024 13:23
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Абстрагирование ваших циклов демонстрирует, почему это не работает.

for i in (1, 2, 3):
    for j in (1, 2):
        if i == j:
            print('match', i)
        else:
            print('no match', i)

match 1
no match 1
no match 2
match 2
no match 3
no match 3

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

Изменение этого цикла на цикл for/else — оптимальный способ определить, когда ни одно число не совпадает.

for i in (1, 2, 3):
    for j in (1, 2):
        if i == j:
            print('match', i)
            break
    else:
        print('no match', i)

match 1
match 2
no match 3

Тогда ваша функция станет такой:

def filter_data(data, match_d=None, trim_matches=False):
    result_matches = {}  # stores matched
    result_unmatches = {}  # stores not matched

    # loop every record in data
    for key, value in data.items():

        # match record with filter criteria
        for search_string, search_key_name in match_d.items():

            if search_string == value[search_key_name]:
                result_matches[key] = value
                break
        else:
            result_unmatches[key] = value

    if trim_matches:
        return result_unmatches
    return result_matches

# match: {0: {'name': 'one'}, 1: {'name': 'two'}}
# no match: {2: {'name': 'three'}, 3: {'name': 'four'}, 4: {'name': 'five'}}

Обратите внимание: если в вашем словаре data есть элементы с повторяющимися именами, цикл for/else не будет работать и выдаст вам только первое совпадение. Чтобы получить каждое совпадение, вы можете установить переменную, если во время цикла происходят какие-либо совпадения, и пометить ее как «не сопоставленную», только если переменная не была установлена.

for i in (1, 2, 3):
    matched = False
    for j in (1, 1):
        if i == j:
           matched = True
           print('match', i)
    if not matched:
        print('no match', i)

match 1
match 1
no match 2
no match 3
data dict has items with duplicate names я не понимаю, что именно вы имеете в виду? Если у меня есть data_dict = {0: {'name': 'one'}, 1: {'name': 'two'}, 2: {'name': 'three'},3: {'name': 'four'},4: {'name': 'five'}, 5: {name: 'one'}}, т. е. {name: one} использовал два раза? data_dict данные, с которыми я работаю, могут повторяться и иметь одно и то же значение, и их следует показывать несколько раз для всех совпадающих значений.
Roman Toasov 23.02.2024 13:48

Да, именно это я и имею в виду: первое решение, которое я дал, является самым чистым, но если бы было две записи с {name: 'one'}, то было бы получено только первое совпадение.

Peter 26.02.2024 14:01

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