Встроенный itertools
модуль Python на самом деле имеет groupby
функцию, но для этого элементы, которые нужно сгруппировать, должны быть сначала отсортированы таким образом, чтобы элементы, которые нужно сгруппировать, были смежными в списке:
from operator import itemgetter
sortkeyfn = itemgetter(1)
input = [('11013331', 'KAT'), ('9085267', 'NOT'), ('5238761', 'ETH'),
('5349618', 'ETH'), ('11788544', 'NOT'), ('962142', 'ETH'), ('7795297', 'ETH'),
('7341464', 'ETH'), ('9843236', 'KAT'), ('5594916', 'ETH'), ('1550003', 'ETH')]
input.sort(key=sortkeyfn)
Теперь ввод выглядит так:
[('5238761', 'ETH'), ('5349618', 'ETH'), ('962142', 'ETH'), ('7795297', 'ETH'),
('7341464', 'ETH'), ('5594916', 'ETH'), ('1550003', 'ETH'), ('11013331', 'KAT'),
('9843236', 'KAT'), ('9085267', 'NOT'), ('11788544', 'NOT')]
groupby
возвращает последовательность из двух кортежей формы (key, values_iterator)
. Мы хотим превратить это в список dicts, где 'type' является ключом, а 'items' - это список 0-х элементов кортежей, возвращаемых values_iterator. Как это:
from itertools import groupby
result = []
for key,valuesiter in groupby(input, key=sortkeyfn):
result.append(dict(type=key, items=list(v[0] for v in valuesiter)))
Теперь result
содержит желаемый диктат, как указано в вашем вопросе.
Однако вы можете подумать о том, чтобы просто сделать из этого один диктант с ключом по типу и каждым значением, содержащим список значений. В вашей текущей форме, чтобы найти значения для определенного типа, вам придется перебирать список, чтобы найти dict, содержащий соответствующий ключ type, а затем получить из него элемент items. Если вы используете одиночный dict вместо списка dict из 1 элемента, вы можете найти элементы для определенного типа с помощью поиска с одним ключом в главном dict. При использовании groupby
это будет выглядеть так:
result = {}
for key,valuesiter in groupby(input, key=sortkeyfn):
result[key] = list(v[0] for v in valuesiter)
result
теперь содержит этот dict (он похож на промежуточный res
defaultdict в ответе @ KennyTM):
{'NOT': ['9085267', '11788544'],
'ETH': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'],
'KAT': ['11013331', '9843236']}
(Если вы хотите сократить это до однострочника, вы можете:
result = dict((key,list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn))
или используя новомодную форму понимания слов:
result = {key:list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn)}
[('11013331', 'red', 'KAT'), ('9085267', 'blue' 'KAT')]
где последний элемент кортежа является ключевым, а первые два - значением. Результат должен быть таким: result = [{type: 'KAT', items: [('11013331', red), ('9085267', blue)]}]