Я сделал функцию для цикла по массиву и фильтрации результатов.
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.
Редактировать: понимая, что отладка трудна, я пошел дальше, раскрасил и расположил вывод, теперь легко увидеть, что происходит.
@MichaelButscher, здорово, это сработало! я пробовал что-то подобное, но меня раздражала сложность функции и сложность предоставленных данных, я упростил ее только перед публикацией в StackOverflow, думаю, в следующий раз мне не стоит быть таким ленивым и сделать простую версию функции для поиска простое решение. Не понял, что второй цикл выполняет только сравнение с фильтром, присвоение не обязательно должно происходить внутри второго цикла.






Абстрагирование ваших циклов демонстрирует, почему это не работает.
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 данные, с которыми я работаю, могут повторяться и иметь одно и то же значение, и их следует показывать несколько раз для всех совпадающих значений.
Да, именно это я и имею в виду: первое решение, которое я дал, является самым чистым, но если бы было две записи с {name: 'one'}, то было бы получено только первое совпадение.
Установите дополнительную переменную перед внутренним циклом for, например. г.
matched = False. Если вы нашли совпадение, установите егоTrue. После внутреннего цикла for добавьте запись вresult_unmatches, если переменная все еще равнаFalse.