Как мне использовать itertools.groupby()?
Я не смог найти понятного объяснения того, как на самом деле использовать функцию 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
сам итератор возвращает итераторы.
Вот пример этого, использующий более понятные имена переменных:
from itertools import groupby
things = [("animal", "bear"), ("animal", "duck"), ("plant", "cactus"), ("vehicle", "speed boat"), ("vehicle", "school bus")]
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 + ".")
Это даст вам результат:
животные: медведь и утка.
растения: кактус.
транспортные средства: скоростной катер и школьный автобус.
Ответ 2
itertools.groupby
is a tool for grouping items.
From the docs, we glean further what it might do:
# [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
>>> def print_groupby(iterable, keyfunc=None):
... for k, g in it.groupby(iterable, keyfunc):
... print("key: '{}'--> group: {}".format(k, list(g)))
# Feature A: group consecutive occurrences
>>> print_groupby("BCAACACAADBBB")
key: 'B'--> group: ['B']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A', 'A']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A', 'A']
key: 'D'--> group: ['D']
key: 'B'--> group: ['B', 'B', 'B']
# Feature B: group all occurrences
>>> print_groupby(sorted("BCAACACAADBBB"))
key: 'A'--> group: ['A', 'A', 'A', 'A', 'A']
key: 'B'--> group: ['B', 'B', 'B', 'B']
key: 'C'--> group: ['C', 'C', 'C']
key: 'D'--> group: ['D']
# Feature C: group by a key function
>>> # islower = lambda s: s.islower() # equivalent
>>> def islower(s):
... """Return True if a string is lowercase, else False."""
... return s.islower()
>>> print_groupby(sorted("bCAaCacAADBbB"), keyfunc=islower)
key: 'False'--> group: ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'D']
key: 'True'--> group: ['a', 'a', 'b', 'b', 'c']
Uses
- Anagrams (see notebook)
- Binning
- Group odd and even numbers
- Group a list by values
- Remove duplicate elements
- Find indices of repeated elements in an array
- Split an array into n-sized chunks
- Find corresponding elements between two lists
- Compression algorithm (see notebook)/Run Length Encoding
- Grouping letters by length, key function (see notebook)
- Consecutive values over a threshold (see notebook)
- Find ranges of numbers in a list or continuous items (see docs)
- Find all related longest sequences
- Take consecutive sequences that meet a condition (see related post)
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 не сортирует (и вообще не может) итератор заранее, поэтому группы с одинаковым "ключом" не объединяются.