Идея itertools.groupby
состоит в том, чтобы решить основную проблему: «Я хочу пройтись по последовательности, проанализировать каждую вещь в ней и, в зависимости от процесса анализа, каждую вещь по-своему».groupby
разделяет последовательность на группы, но сохраняет порядок исходной последовательности .
from itertools import groupby
i = groupby(xrange(12), lambda v: v / 3)
results = [(x[0], list(x[1])) for x in i]
print str(results)
Вышеуказанные отпечатки: [(0, [0, 1, 2]), (1, [3, 4, 5]), (2, [6, 7, 8]), (3, [9, 10, 11])]
Вы заметите, чточтобы получить список results
, мне пришлось провести дополнительную обработку.То, что на самом деле дает groupby
, предназначено для итерации:
i = groupby(xrange(12), lambda v: v / 3)
print str(i.next())
Вышеприведенные отпечатки: (0, <itertools._grouper object at 0x020BF3D0>)
Таким образом, идея заключается в том, что в вашей программе вы скажете key, valueiter = i.next()
, testkey
, а затем передайте valueiter
правильной функции / методу обработки.
Так какое здесь значение?Что ж, вам не нужно продолжать тестировать ключ в ваших функциях обработки, чтобы сказать, когда остановиться.groupby
автоматически остановит для вас каждый «итератор».
То, что groupby
делает , а не , в отличие от предложения GROUP BY
в SQL, гарантирует, что все сто же значение ключа из исходного итерируемого обрабатывается сразу.Значения ключа могут повторяться из groupby
.Это оправдано, поскольку цель состоит в том, чтобы сохранить порядок исходной последовательности, а , а не , чтобы накапливать все в памяти.Например:
i = groupby(xrange(6), lambda v: v % 3) # note: modulo division
results = [(x[0], list(x[1])) for x in i]
print str(results)
Приведенные выше отпечатки: [(0, [0]), (1, [1]), (2, [2]), (0, [3]), (1, [4]), (2, [5])]
.Значения ключа повторяются, и каждый подитератор создает только один элемент данных.Это наихудший сценарий с точки зрения производительности для groupby
, и это означает, что вы должны следовать определенной модели при работе с этим инструментом.
Так что-то вроде этого:
i = groupby(xrange(12), lambda v: v / 3)
results = dict([(x[0], list(x[1])) for x in i]) # beware of dict() here!
print str(results)
правильно только в том случае, если вы знаете априори , что ваши значения ключа будут никогда повторяться.