Использование itertools.groupby
:
>>> import itertools
>>> import operator
>>> foo = [("a", 1), ("a", 2), ("b", 1), ("c", 1), ("c", 2)]
>>> for group in itertools.groupby(foo, operator.itemgetter(0)):
... print group[0], list(map(operator.itemgetter(1), group[1]))
...
a [1, 2]
b [1]
c [1, 2]
Объяснение:
groupby
, как и следует из названия, группы элементов итератора на куски, основанные на некоторых ключевых функций. То есть он вызывает keyfunc
по первому элементу итерабельного, а затем вытягивает элементы один за другим из итерируемого до тех пор, пока не изменится значение keyfunc
, после чего он получит все элементы, которые он получил до сих пор, и снова начинается с нового ключ. Это также разумно и не потребляет больше памяти, чем необходимо; после того, как значения были получены, они больше не удерживаются groupby
.
Здесь мы группируем элементы ввода на operator.itemgetter(0)
, что является полезной функцией «набор инструментов», которая отображает x
в x[0]
. Другими словами, мы группируем первый элемент кортежа, который является ключом.
Естественно, вам нужно будет написать специальный генератор для считывания ввода (от sys.stdin
, возможно) и дать им один за другим. К счастью, это довольно легко, используя ключевое слово yield
.
Обратите внимание, что это предполагает, что ключи отсортированы. Естественно, если они не отсортированы, вы ничего не можете сделать: вам нужно будет посмотреть до конца ввода, чтобы убедиться, что у вас есть все значения для заданного ключа.