실제로 파이썬 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']
용도
- 아나그램 ( 노트북 참조 )
- 비닝
- 홀수 및 짝수 그룹화
- 값별로 목록을 그룹화
- 중복 요소 제거
- 배열에서 반복되는 요소의 인덱스 찾기
- 배열을 n 크기의 청크로 분할
- 두 목록 사이에서 해당 요소 찾기
- 압축 알고리즘 ( 노트북 참조 ) / 실행 길이 인코딩
- 길이, 키 기능별로 문자 그룹화 ( 노트북 참조 )
- 임계 값을 초과하는 연속적인 값 ( 노트북 참조 )
- 목록 또는 연속 항목 에서 숫자 범위 찾기 ( 문서 참조 )
- 가장 긴 관련 시퀀스 모두 찾기
- 조건에 맞는 연속 시퀀스를 가져옵니다 ( 관련 게시물 참조 )
참고 : 후자의 예제 중 일부는 Víctor Terrón의 PyCon (토크) (스페인어) , “Itertools와 함께 새벽에 쿵푸” 에서 파생되었습니다 . 소스 코드 참조groupby
C로 작성된 .
* 모든 항목을 통과하고 비교하여 결과에 영향을주는 기능입니다. 주요 기능이있는 다른 객체에는 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.groupby
SQL 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.
하나의 그룹 만 기대할 수있는 반면, 차량에는 두 그룹이 있습니다