Vra

Ek kon nie 'n verstaanbare verduideliking kry van hoe om Python's eintlik te gebruik nie itertools.groupby() funksie.Wat ek probeer doen is dit:

  • Neem 'n lys - in hierdie geval, die kinders van 'n geobjektiveerde lxml element
  • Verdeel dit in groepe op grond van sekere kriteria
  • Herhaal dan later oor elkeen van hierdie groepe afsonderlik.

Ek het geresenseer die dokumentasie, en die voorbeelde, maar ek het probleme gehad om hulle verder as 'n eenvoudige lys nommers toe te pas.

So, hoe gebruik ek van itertools.groupby()?Is daar 'n ander tegniek wat ek moet gebruik?Aanwysings na goeie "voorvereiste" lees sal ook waardeer word.

Was dit nuttig?

Oplossing

BELANGRIKE NOTA: Jy moet sorteer jou data eerste.


Die deel wat ek nie gekry het nie, is dit in die voorbeeldkonstruksie

groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
   groups.append(list(g))    # Store group iterator as a list
   uniquekeys.append(k)

k is die huidige groepsleutel, en g is 'n iterator wat jy kan gebruik om te herhaal oor die groep wat deur daardie groepsleutel gedefinieer is.Met ander woorde, die groupby iterator self gee iterators terug.

Hier is 'n voorbeeld daarvan, met behulp van duideliker veranderlike name:

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

Dit sal vir jou die uitset gee:

'n Beer is 'n dier.
'n Eend is 'n dier.

'n Kaktus is 'n plant.

'n Spoedboot is 'n voertuig.
'n Skoolbus is 'n voertuig.

In hierdie voorbeeld, things is 'n lys van tupels waar die eerste item in elke tupel die groep is waaraan die tweede item behoort.

Die groupby() funksie neem twee argumente:(1) die data om te groepeer en (2) die funksie om dit mee te groepeer.

Hier, lambda x: x[0] vertel groupby() om die eerste item in elke tupel as die groepsleutel te gebruik.

In bogenoemde for verklaring, groupby gee drie (sleutel, groepiterator) pare terug - een keer vir elke unieke sleutel.Jy kan die teruggekeerde iterator gebruik om oor elke individuele item in daardie groep te herhaal.

Hier is 'n effens ander voorbeeld met dieselfde data, met behulp van 'n lysbegrip:

for key, group in groupby(things, lambda x: x[0]):
    listOfThings = " and ".join([thing[1] for thing in group])
    print key + "s:  " + listOfThings + "."

Dit sal vir jou die uitset gee:

diere:beer en eend.
plante:kaktus.
voertuie:spoedboot en skoolbus.

Ander wenke

Kan jy vir ons jou kode wys?

Die voorbeeld op die Python-dokumente is redelik eenvoudig:

groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
    groups.append(list(g))      # Store group iterator as a list
    uniquekeys.append(k)

So in jou geval is data 'n lys nodusse, keyfunc is waar die logika van jou kriteriafunksie gaan en dan groupby() groepeer die data.

Jy moet versigtig wees om sorteer die data volgens die kriteria voordat jy bel groupby of dit sal nie werk nie. groupby metode herhaal eintlik net deur 'n lys en wanneer die sleutel verander, skep dit 'n nuwe groep.

'n Netjiese truuk met groupby is om lengte-kodering in een reël uit te voer:

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

sal vir jou 'n lys van 2-tupels gee waar die eerste element die char is en die 2de die aantal herhalings is.

Wysig:Let daarop dat dit is wat skei itertools.groupby van die SQL GROUP BY semantiek:itertools sorteer nie (en kan oor die algemeen nie) die iterator vooraf nie, so groepe met dieselfde "sleutel" word nie saamgevoeg nie.

itertools.groupby is 'n instrument om items te groepeer.

Van die dokumente, leer ons verder wat dit kan doen:

# [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 voorwerpe lewer sleutel-groeppare waar die groep 'n kragopwekker is.

Kenmerke

  • A.Groepeer opeenvolgende items saam
  • B.Groepeer alle voorkomste van 'n item, gegee 'n gesorteerde iterable
  • C.Spesifiseer hoe om items met 'n sleutelfunksie te groepeer

Vergelykings

# Define a printer for comparing outputs
>>> def print_groupby(iterable, key=None):
...    for k, g in it.groupby(iterable, key):
...        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
>>> key = lambda x: x.islower()
>>> print_groupby(sorted("bCAaCacAADBbB"), key)
key: 'False'--> group: ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'D']
key: 'True'--> group: ['a', 'a', 'b', 'b', 'c']

Gebruike

Let wel:Verskeie van laasgenoemde voorbeelde is afkomstig van Víctor Terrón se PyCon (praat) (Spaans), "Kung Fu at Dawn with Itertools".Sien ook die groupbybronkode geskryf in C.


Reaksie

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

Nog 'n voorbeeld:

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

resultate in

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

Let daarop dat igroup 'n iterator is ('n sub-iterator soos die dokumentasie dit noem).

Dit is nuttig om 'n kragopwekker te verdeel:

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)

Nog 'n voorbeeld van groupby - wanneer die sleutels nie gesorteer is nie.In die volgende voorbeeld word items in xx gegroepeer volgens waardes in yy.In hierdie geval word een stel nulle eerste uitgevoer, gevolg deur 'n stel ene, weer gevolg deur 'n stel nulle.

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])

Produseer:

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

WAARSKUWING:

Die sintaksislys(groepby(...)) sal nie werk soos jy bedoel het nie.Dit lyk asof dit die interne iterator-voorwerpe vernietig, dus gebruik

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

sal produseer:

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

In plaas daarvan, van list(groupby(...)), probeer [(k, list(g)) vir k,g in groupby(...)], of as jy daardie sintaksis dikwels gebruik,

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

en kry toegang tot die groupby-funksionaliteit terwyl jy daardie lastige (vir klein data) iterators almal saam vermy.

Ek wil nog 'n voorbeeld gee waar groupby sonder sort nie werk nie.Aangepas uit voorbeeld deur 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 " "

uitset is

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.

daar is twee groepe met voertuig, terwyl mens net een groep kan verwag

@CaptSolo, ek het jou voorbeeld probeer, maar dit het nie gewerk nie.

from itertools import groupby 
[(c,len(list(cs))) for c,cs in groupby('Pedro Manoel')]

Uitset:

[('P', 1), ('e', 1), ('d', 1), ('r', 1), ('o', 1), (' ', 1), ('M', 1), ('a', 1), ('n', 1), ('o', 1), ('e', 1), ('l', 1)]

Soos jy kan sien, is daar twee o's en twee e's, maar hulle het in aparte groepe gekom.Dit is toe dat ek besef het dat jy die lys wat na die groupby-funksie oorgedra moet moet sorteer.Dus, die korrekte gebruik sou wees:

name = list('Pedro Manoel')
name.sort()
[(c,len(list(cs))) for c,cs in groupby(name)]

Uitset:

[(' ', 1), ('M', 1), ('P', 1), ('a', 1), ('d', 1), ('e', 2), ('l', 1), ('n', 1), ('o', 2), ('r', 1)]

Onthou net, as die lys nie gesorteer is nie, die groupby-funksie sal nie werk nie!

Hoe gebruik ek Python se itertools.groupby()?

Jy kan groupby gebruik om dinge te groepeer om oor te herhaal.Jy gee groupby 'n herhaalbare en 'n opsionele sleutel funksie/oproepbaar waarmee die items gekontroleer kan word soos hulle uit die iterable kom, en dit gee 'n iterator terug wat 'n twee-tuple gee van die resultaat van die sleutel oproepbare en die werklike items in 'n ander iterable.Van die hulp:

groupby(iterable[, keyfunc]) -> create an iterator which returns
(key, sub-iterator) grouped by each value of key(value).

Hier is 'n voorbeeld van groepeer deur 'n koroutine te gebruik om volgens 'n telling te groepeer, dit gebruik 'n sleutel wat oproepbaar is (in hierdie geval, coroutine.send) om net die telling uit te spoeg vir hoeveel iterasies en 'n gegroepeerde sub-iterator van elemente:

import itertools


def grouper(iterable, n):
    def coroutine(n):
        yield # queue up coroutine
        for i in itertools.count():
            for j in range(n):
                yield i
    groups = coroutine(n)
    next(groups) # queue up coroutine

    for c, objs in itertools.groupby(iterable, groups.send):
        yield c, list(objs)
    # or instead of materializing a list of objs, just:
    # return itertools.groupby(iterable, groups.send)

list(grouper(range(10), 3))

afdrukke

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

Sorteer en groepeer volgens

from itertools import groupby

val = [{'name': 'satyajit', 'address': 'btm', 'pin': 560076}, 
       {'name': 'Mukul', 'address': 'Silk board', 'pin': 560078},
       {'name': 'Preetam', 'address': 'btm', 'pin': 560076}]


for pin, list_data in groupby(sorted(val, key=lambda k: k['pin']),lambda x: x['pin']):
...     print pin
...     for rec in list_data:
...             print rec
... 
o/p:

560076
{'name': 'satyajit', 'pin': 560076, 'address': 'btm'}
{'name': 'Preetam', 'pin': 560076, 'address': 'btm'}
560078
{'name': 'Mukul', 'pin': 560078, 'address': 'Silk board'}

Een nuttige voorbeeld wat ek teëgekom het, kan nuttig wees:

from itertools import groupby

#user input

myinput = input()

#creating empty list to store output

myoutput = []

for k,g in groupby(myinput):

    myoutput.append((len(list(g)),int(k)))

print(*myoutput)

Voorbeeldinvoer:14445221

Voorbeeld uitset:(1,1) (3,4) (1,5) (2,2) (1,1)

Jy kan jou eie groupby-funksie skryf:

           def groupby(data):
                kv = {}
                for k,v in data:
                    if k not in kv:
                         kv[k]=[v]
                    else:
                        kv[k].append(v)
           return kv

     Run on ipython:
       In [10]: data = [('a', 1), ('b',2),('a',2)]

        In [11]: groupby(data)
        Out[11]: {'a': [1, 2], 'b': [2]}
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top