itertools.groupby ()를 어떻게 사용합니까? 방법에 대한

실제로 파이썬 itertools.groupby()함수를 사용하는 방법에 대한 이해하기 쉬운 설명을 찾지 못했습니다 . 내가하려는 것은 이것입니다 :

  • 목록을 작성하십시오-이 경우 객관적인 lxml요소 의 자식
  • 몇 가지 기준에 따라 그룹으로 나눕니다.
  • 그런 다음 나중에 각 그룹을 개별적으로 반복하십시오.

설명서예제를 검토 했지만 간단한 숫자 목록을 넘어서 적용하는 데 문제가있었습니다.

그래서 어떻게 사용 itertools.groupby()합니까? 사용해야하는 다른 기술이 있습니까? 좋은 “전제 조건”독서에 대한 포인터도 감사하겠습니다.



답변

중요 참고 : 먼저 데이터정렬해야합니다 .


내가 얻지 못한 부분은 예제 구성에서

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 + "."

이것은 당신에게 출력을 줄 것입니다 :

동물 : 곰과 오리.
식물 : 선인장.
차량 : 스피드 보트 및 스쿨 버스.


답변

파이썬 문서의 예는 매우 간단합니다.

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메소드는 실제로 목록을 반복하며 키가 변경 될 때마다 새 그룹을 만듭니다.


답변

itertools.groupby 항목을 그룹화하는 도구입니다.

에서 워드 프로세서 , 우리는 할 수있는 것을 더욱 수집합니다 :

# [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 객체는 그룹이 생성기 인 키 그룹 쌍을 생성합니다.

풍모

  • A. 연속 항목을 그룹화
  • B. iterable에 따라 항목의 모든 항목을 그룹화
  • C. 항목을 그룹화하는 방법 지정 키 기능으로 *

비교

# 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
>>> # keyfunc = lambda s: s.islower()                      # equivalent
>>> def keyfunc(s):
...     """Return a True if a string is lowercase, else False."""
...     return s.islower()
>>> print_groupby(sorted("bCAaCacAADBbB"), keyfunc)
key: 'False'--> group: ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'D']
key: 'True'--> group: ['a', 'a', 'b', 'b', 'c']

용도

참고 : 후자의 예제 중 일부는 Víctor Terrón의 PyCon (토크) (스페인어) , “Itertools와 함께 새벽에 쿵푸” 에서 파생되었습니다 . 소스 코드 참조groupbyC로 작성된 .

* 모든 항목을 통과하고 비교하여 결과에 영향을주는 기능입니다. 주요 기능이있는 다른 객체에는 sorted(), max()및가 min()있습니다.


응답

# OP: Yes, you can use `groupby`, e.g. 
[do_something(list(g)) for _, g in groupby(lxml_elements, criteria_func)]


답변

groupby를 사용하는 깔끔한 요령은 한 줄에 길이 인코딩을 실행하는 것입니다.

[(c,len(list(cgen))) for c,cgen in groupby(some_string)]

첫 번째 요소는 문자이고 두 번째 요소는 반복 횟수 인 2 개의 튜플 목록을 제공합니다.

편집 : 이것은 itertools.groupbySQL GROUP BY의미 와 구별 됩니다 . itertools는 미리 반복자를 정렬하지 않으며 일반적으로 동일한 “키”를 가진 그룹은 병합되지 않습니다.


답변

또 다른 예:

for key, igroup in itertools.groupby(xrange(12), lambda x: x // 5):
    print key, list(igroup)

결과

0 [0, 1, 2, 3, 4]
1 [5, 6, 7, 8, 9]
2 [10, 11]

igroup은 이터레이터 (문서에서 호출하는 하위 이터레이터)입니다.

발전기를 청크 할 때 유용합니다.

def chunker(items, chunk_size):
    '''Group items in chunks of chunk_size'''
    for _key, group in itertools.groupby(enumerate(items), lambda x: x[0] // chunk_size):
        yield (g[1] for g in group)

with open('file.txt') as fobj:
    for chunk in chunker(fobj):
        process(chunk)

그룹 별의 또 다른 예-키가 정렬되지 않은 경우. 다음 예에서 xx의 항목은 yy의 값으로 그룹화됩니다. 이 경우, 한 세트의 0이 먼저 출력되고, 그 뒤에 1 세트가, 다시 제로 세트가 출력됩니다.

xx = range(10)
yy = [0, 0, 0, 1, 1, 1, 0, 0, 0, 0]
for group in itertools.groupby(iter(xx), lambda x: yy[x]):
    print group[0], list(group[1])

생산 :

0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]


답변

경고:

구문 목록 (groupby (…))이 원하는 방식으로 작동하지 않습니다. 내부 반복자 객체를 파괴하는 것 같습니다.

for x in list(groupby(range(10))):
    print(list(x[1]))

생산할 것이다 :

[]
[]
[]
[]
[]
[]
[]
[]
[]
[9]

대신 list (groupby (…)) 대신 groupby (…)]에서 k, g에 대해 [(k, list (g))를 시도하거나 해당 구문을 자주 사용하는 경우,

def groupbylist(*args, **kwargs):
    return [(k, list(g)) for k, g in groupby(*args, **kwargs)]

작은 데이터의 경우 반복자를 피하면서 그룹 별 기능에 액세스 할 수 있습니다.


답변

정렬되지 않은 groupby가 작동하지 않는 다른 예를 제공하고 싶습니다. James Sulak의 예에서 발췌

from itertools import groupby

things = [("vehicle", "bear"), ("animal", "duck"), ("animal", "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 " "

출력은

A bear is a vehicle.

A duck is a animal.
A cactus is a animal.

A speed boat is a vehicle.
A school bus is a vehicle.

하나의 그룹 만 기대할 수있는 반면, 차량에는 두 그룹이 있습니다