سؤال

لم أكن قادرة على العثور مفهومة شرح كيفية استخدام بايثون 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() استخدام البند الأول في كل tuple كما التجميع الرئيسية.

في أعلاه 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 الطريقة في الواقع مجرد تتكرر خلال قائمة كلما التغييرات الرئيسية يخلق مجموعة جديدة.

أ neato خدعة مع groupby هو ترميز طول التشغيل في سطر واحد:

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

سوف أعطيك قائمة من 2-الصفوف من حيث العنصر الأول هو شار و 2 هو عدد التكرار.

تحرير:لاحظ أن هذا هو ما يفصل itertools.groupby من SQL GROUP BY دلالات:itertools لا (و بشكل عام لا يمكن) نوع مكرر مسبقا ، حتى المجموعات مع نفس "مفتاح" ليست دمجها.

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.مجموعة متتالية من العناصر معا
  • ب.المجموعة كافة تواجدات عنصر ، نظرا فرز iterable
  • C.تحديد كيفية تجميع العناصر مع مفتاح وظيفة

مقارنات

# 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']

يستخدم

ملاحظة:العديد من الأمثلة الأخيرة مستمدة من فيكتور تيرون هو PyCon (الحديث) (إسبانية), "الكونغ فو عند الفجر مع Itertools".انظر أيضا groupbyالتعليمات البرمجية المصدر مكتوب في C.


رد

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

مثال آخر:

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 هو مكرر (شبه مكرر لأن الوثائق يسميها).

هذا هو مفيدة chunking مولد:

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)

مثال آخر من groupby - عندما مفاتيح لم يتم فرزها.في المثال التالي, العناصر في العشرين بحسب القيم في السنة.في هذه الحالة مجموعة من الأصفار هو الإخراج الأول ، تليها مجموعة منها ، ثم مرة أخرى من قبل مجموعة من الأصفار.

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]

بدلا من قائمة(groupby (...)) ، في محاولة [(k, قائمة(ز)) k,g في groupby (...)] ، أو إذا كنت تستخدم هذه الجملة في كثير من الأحيان ،

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

والحصول على groupby وظائف وتجنب تلك غذر (الصغيرة البيانات) التكرار كل ذلك معا.

أود أن أعطي مثالا آخر حيث groupby دون نوع لا يعمل.مقتبس من المثال جيمس 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.

هناك مجموعتين مع سيارة, في حين يمكن للمرء أن نتوقع مجموعة واحدة فقط

@CaptSolo, حاولت سبيل المثال ، ولكنه لم ينجح.

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

الإخراج:

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

كما ترون, هناك نوعان o واثنين ه ، ولكن لأنهم وصلوا إلى مجموعات منفصلة.هذا عندما أدركت تحتاج إلى فرز قائمة تمريرها إلى groupby وظيفة.لذا ، فإن الاستخدام الصحيح ليكون:

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

الإخراج:

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

فقط تذكر, إذا لا فرز القائمة ، groupby وظيفة لا تعمل!

كيف يمكنني استخدام بايثون itertools.groupby()?

يمكنك استخدام groupby إلى مجموعة الأشياء إلى تكرار أكثر.كنت تعطي groupby وهو iterable ، الاختياري الرئيسية وظيفة/للاستدعاء الذي للتحقق من البنود كما أنها تأتي من iterable ، تقوم بإرجاع التكرار الذي يعطي اثنين tuple النتيجة الرئيسية للاستدعاء و العناصر الفعلية في آخر iterable.من مساعدة:

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

هنا مثال من groupby باستخدام coroutine إلى مجموعة من العد ، فإنه يستخدم مفتاح المستحقة (في هذه الحالة ، coroutine.send) فقط بصق عد عن ذلك العديد من التكرارات و تجميع الفرعية مكرر من العناصر:

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

طباعة

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

الفرز و groupby

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'}

واحدة مفيدة سبيل المثال التي صادفت قد تكون مفيدة:

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)

نموذج المدخلات:14445221

عينة الإخراج:(1,1) (3,4) (1,5) (2,2) (1,1)

يمكنك الكتابة الخاصة groupby وظيفة:

           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]}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top