Я не смог найти понятного объяснения того, как на самом деле использовать функцию Python itertools.groupby(). Что я пытаюсь сделать, так это:
Возьмите список - в данном случае дочерние элементы объективированного lxml элемента
Разделите его на группы на основе некоторых критериев
Затем выполните итерацию по каждой из этих групп отдельно.
Я просмотрел документацию, но у меня возникли проблемы при попытке применить их помимо простого списка чисел.
Итак, как мне использовать of itertools.groupby()? Есть ли другой метод, который я должен использовать? Также были бы оценены указатели на хорошее чтение "предварительных условий".
Переведено автоматически
Ответ 1
ВАЖНОЕ ПРИМЕЧАНИЕ: Возможно, вампридется сначала отсортировать свои данные.
Часть, которую я не понял, это то, что в конструкции примера
groups = [] uniquekeys = [] for k, g in groupby(data, keyfunc): groups.append(list(g)) # Store group iterator as a list uniquekeys.append(k)
k это текущий ключ группировки и g это итератор, который вы можете использовать для перебора группы, определенной этим ключом группировки. Другими словами, groupby сам итератор возвращает итераторы.
Вот пример этого, использующий более понятные имена переменных:
for key, group in groupby(things, lambda x: x[0]): for thing in group: print("A %s is a %s." % (thing[1], key)) print("")
Это даст вам результат:
Медведь - это животное. Утка - это животное.
Кактус - это растение.
Скоростной катер - это транспортное средство. Школьный автобус - это транспортное средство.
В этом примере things представляет собой список кортежей, где первым элементом в каждом кортеже является группа, к которой принадлежит второй элемент.
groupby() Функция принимает два аргумента: (1) данные для группировки и (2) функцию, с помощью которой они группируются.
Здесь lambda x: x[0] указывает groupby() использовать первый элемент в каждом кортеже в качестве ключа группировки.
В приведенном выше for заявлении groupby возвращает три пары (ключ, групповой итератор) - по одному разу для каждого уникального ключа. Вы можете использовать возвращаемый итератор для перебора каждого отдельного элемента в этой группе.
Вот немного другой пример с теми же данными, использующий представление списка:
for key, group in groupby(things, lambda x: x[0]): listOfThings = " and ".join([thing[1] for thing in group]) print(key + "s: " + listOfThings + ".")
Это даст вам результат:
животные: медведь и утка. растения: кактус. транспортные средства: скоростной катер и школьный автобус.
# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
groupby objects yield key-group pairs where the group is a generator.
Features
A. Group consecutive items together
B. Group all occurrences of an item, given a sorted iterable
C. Specify how to group items with a key function*
Comparisons
# Define a printer for comparing outputs >>> defprint_groupby(iterable, keyfunc=None): ... for k, g in it.groupby(iterable, keyfunc): ... print("key: '{}'--> group: {}".format(k, list(g)))
Note: Several of the latter examples derive from Víctor Terrón's PyCon (talk)(Spanish), "Kung Fu at Dawn with Itertools". See also the groupby source code written in C.
* A function where all items are passed through and compared, influencing the result. Other objects with key functions include sorted(), max() and min().
Ответ
# OP: Yes, you can use `groupby`, e.g. [do_something(list(g)) for _, g in groupby(lxml_elements, criteria_func)]
Ответ 3
Пример в документах Python довольно прост:
groups = [] uniquekeys = [] for k, g in groupby(data, keyfunc): groups.append(list(g)) # Store group iterator as a list uniquekeys.append(k)
Итак, в вашем случае данные представляют собой список узлов, keyfunc это то, куда направляется логика вашей функции критериев, а затем groupby() группирует данные.
Вы должны быть осторожны, чтобы отсортировать данные по критериям перед вызовом, groupby иначе это не сработает. groupby метод на самом деле просто выполняет итерацию по списку и всякий раз, когда меняется ключ, создает новую группу.
Ответ 4
Простой трюк с groupby заключается в выполнении кодирования длины в одной строке:
[(c,len(list(cgen))) for c,cgen in groupby(some_string)]
выдаст вам список из 2-х кортежей, где первым элементом является символ, а вторым - количество повторений.
Редактировать: Обратите внимание, что это то, что отличает семантику itertools.groupby от SQL GROUP BY: itertools не сортирует (и вообще не может) итератор заранее, поэтому группы с одинаковым "ключом" не объединяются.