كيف يمكنني استخدام بايثون 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()
استخدام البند الأول في كل 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']
يستخدم
- الجناس (انظر دفتر)
- Binning
- مجموعة الأعداد الفردية والزوجية
- مجموعة قائمة من القيم
- إزالة العناصر المكررة
- العثور على مؤشرات تكرار العناصر في مجموعة
- تقسيم مجموعة إلى n-الحجم قطع
- العثور على العناصر المقابلة بين قائمتين
- خوارزمية ضغط (انظر دفتر)/ترميز طول التشغيل
- تجميع الرسائل حسب طول مفتاح وظيفة (انظر دفتر)
- قيم متتالية على عتبة (انظر دفتر)
- العثور على سلاسل من الأرقام في قائمة أو المستمر البنود (انظر مستندات)
- إيجاد جميع أطول تسلسل
- تأخذ على التوالي متواليات التي تلبي شرط (انظر آخر ذات الصلة)
ملاحظة:العديد من الأمثلة الأخيرة مستمدة من فيكتور تيرون هو 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]}