Как эффективно классифицировать список словарей по значению ключа в python?
У меня есть список словарей в Python, которые я хочу классифицировать их на основе значения ключа, который существует во всех словарях и обрабатывать каждую категорию в отдельности. Я не знаю, каковы значения, я просто знаю, что существует специальный ключ. Вот список:
dictList = [
{'name': 'name1', 'type': 'type1', 'id': '14464'},
{'name': 'name2', 'type': 'type1', 'id': '26464'},
{'name': 'name3', 'type': 'type3', 'id': '36464'},
{'name': 'name4', 'type': 'type5', 'id': '43464'},
{'name': 'name5', 'type': 'type2', 'id': '68885'}
]
Это код, который я сейчас использую:
while len(dictList):
category = [l for l in dictList if l['type'] == dictList[0]['type']]
processingMethod(category)
for item in category:
dictList.remove(item)
Эта итерация в приведенном выше списке даст мне следующий результат:
Iteration 1:
category = [
{'name': 'name1', 'type': 'type1', 'id': '14464'},
{'name': 'name2', 'type': 'type1', 'id': '26464'},
]
Iteration 2:
category = [
{'name': 'name3', 'type': 'type3', 'id': '36464'}
]
Iteration 3:
category = [
{'name': 'name4', 'type': 'type5', 'id': '43464'}
]
Iteration 4:
category = [
{'name': 'name5', 'type': 'type2', 'id': '68885'}
]
Каждый раз я получаю категорию, обрабатываю ее и, наконец, удаляю обработанные элементы, чтобы перебрать оставшиеся элементы, пока не останется ни одного элемента. Есть идеи, чтобы сделать это лучше?
2 ответа
Ваш код может быть переписан с помощью itertools.groupby
for _, category in itertools.groupby(dictList, key=lambda item:item['type']):
processingMethod(list(category))
Или, если processingMethod может обрабатывать iterable
,
for _, category in itertools.groupby(dictList, key=lambda item:item['type']):
processingMethod(category)
Если l['type']
Хашим для каждого l
в dictList
Вот возможное, несколько элегантное решение:
bins = {}
for l in dictList:
if l['type'] in bins:
bins[l['type']].append(l)
else:
bins[l['type']] = [l]
for category in bins.itervalues():
processingMethod(category)
Идея в том, что сначала мы разберем все l
с мусорными ведрами, используя l['type']
в качестве ключа; во-вторых, мы обработаем каждую корзину.
Если l['type']
не гарантируется быть хэшируемым для каждого l
в dictList
, подход по сути тот же, но нам придется использовать список кортежей вместо dict, что означает, что это немного менее эффективно:
bins = []
for l in dictList:
for bin in bins:
if bin[0] == l['type']:
bin[1].append(l)
break
else:
bins.append((l['type'], [l]))
for _, category in bins:
processingMethod(category)