2016-12-31 9 views
4

При чтении документации на python я наткнулся на функцию itertools.groupby() . Это было не очень просто, поэтому я решил найти некоторую информацию здесь о stackoverflow. Я нашел что-то от How do I use Python's itertools.groupby()?.Что такое itertools.groupby()?

Здесь, как представляется, мало информации об этом здесь и в документации, поэтому я решил опубликовать свои замечания для комментариев.

Благодаря

+0

ли вы проверили [ 'grouby()' документ] (https://docs.python.org/2/library/itertools .html # itertools.groupby)? Какая часть в этом не была прямой? –

+0

@MoinuddinQuadri В первом предложении вопроса OP говорится, что они читают документацию Python. –

+0

вы задаете вопрос, на который вы подготовили подробный ответ? действительно? почему не все это в вопросе и оставить раздел ответов для обсуждения? –

ответ

6

Для начала, вы можете прочитать в документации here.

Поместите то, что я считаю самым важным пунктом в первую очередь. Надеюсь, что причина станет понятной после примеров.

ВСЕГДА SORT ПУНКТЫ с тем же ключом, который будет использоваться для группирования, чтобы избежать Неожиданные результаты

itertools.groupby(iterable, key=None or some func) принимает список итерируемыми и группирует их на основе указанного ключа. Ключ определяет, какое действие следует применять к каждому индивидуальному итерабельному, результат которого затем используется как заголовок для каждой группировки элементов; элементы, которые в конечном итоге имеют одинаковое значение «ключа», попадают в одну группу.

Возвращаемое значение является итерируемым, аналогичным словарю, в том, что оно имеет форму {key : value}.

Пример 1

# note here that the tuple counts as one item in this list. I did not 
# specify any key, so each item in the list is a key on its own. 
c = groupby(['goat', 'dog', 'cow', 1, 1, 2, 3, 11, 10, ('persons', 'man', 'woman')]) 
dic = {} 
for k, v in c: 
    dic[k] = list(v) 
dic 

Результаты в

{1: [1, 1], 
'goat': ['goat'], 
3: [3], 
'cow': ['cow'], 
('persons', 'man', 'woman'): [('persons', 'man', 'woman')], 
10: [10], 
11: [11], 
2: [2], 
'dog': ['dog']} 

Пример 2

# notice here that mulato and camel don't show up. only the last element with a certain key shows up, like replacing earlier result 
# the last result for c actually wipes out two previous results. 

list_things = ['goat', 'dog', 'donkey', 'mulato', 'cow', 'cat', ('persons', 'man', 'woman'), \ 
       'wombat', 'mongoose', 'malloo', 'camel'] 
c = groupby(list_things, key=lambda x: x[0]) 
dic = {} 
for k, v in c: 
    dic[k] = list(v) 
dic 

приводит к

{'c': ['camel'], 
'd': ['dog', 'donkey'], 
'g': ['goat'], 
'm': ['mongoose', 'malloo'], 
'persons': [('persons', 'man', 'woman')], 
'w': ['wombat']} 

Теперь для отсортированного версии

# but observe the sorted version where I have the data sorted first on same key I used for grouping 
list_things = ['goat', 'dog', 'donkey', 'mulato', 'cow', 'cat', ('persons', 'man', 'woman'), \ 
       'wombat', 'mongoose', 'malloo', 'camel'] 
sorted_list = sorted(list_things, key = lambda x: x[0]) 
print(sorted_list) 
print() 
c = groupby(sorted_list, key=lambda x: x[0]) 
dic = {} 
for k, v in c: 
    dic[k] = list(v) 
dic 

приводит к

['cow', 'cat', 'camel', 'dog', 'donkey', 'goat', 'mulato', 'mongoose', 'malloo', ('persons', 'man', 'woman'), 'wombat'] 
{'c': ['cow', 'cat', 'camel'], 
'd': ['dog', 'donkey'], 
'g': ['goat'], 
'm': ['mulato', 'mongoose', 'malloo'], 
'persons': [('persons', 'man', 'woman')], 
'w': ['wombat']} 

Пример 3

things = [("animal", "bear"), ("animal", "duck"), ("plant", "cactus"), ("vehicle", "harley"), \ 
      ("vehicle", "speed boat"), ("vehicle", "school bus")] 
dic = {} 
f = lambda x: x[0] 
for key, group in groupby(sorted(things, key=f), f): 
    dic[key] = list(group) 
dic 

приводит к

{'animal': [('animal', 'bear'), ('animal', 'duck')], 
'plant': [('plant', 'cactus')], 
'vehicle': [('vehicle', 'harley'), 
    ('vehicle', 'speed boat'), 
    ('vehicle', 'school bus')]} 

Теперь для отсортированного версии. Я заменил кортежи на списки здесь. Те же результаты в любом случае.

things = [["animal", "bear"], ["animal", "duck"], ["vehicle", "harley"], ["plant", "cactus"], \ 
      ["vehicle", "speed boat"], ["vehicle", "school bus"]] 
dic = {} 
f = lambda x: x[0] 
for key, group in groupby(sorted(things, key=f), f): 
    dic[key] = list(group) 
dic 

приводит

{'animal': [['animal', 'bear'], ['animal', 'duck']], 
'plant': [['plant', 'cactus']], 
'vehicle': [['vehicle', 'harley'], 
    ['vehicle', 'speed boat'], 
    ['vehicle', 'school bus']]} 
+0

"' itertools.groupby (iterable, key = None или какой-либо func) 'принимает список итераций" Требуется ли список итераций или просто итерабельный? Список является итерируемым. – Tagc

+0

Документы не указаны явно. Но из приведенных мною примеров вы можете видеть, что я использовал список и список вложенных списков. Таким образом, он может принимать «итерируемый» (пример 1), а также «список итераций» (пример 2). Вы даже можете пройти в одной строке, и вы все еще будете в бизнесе. – Parousia

2

Как всегда documentation of the function должно быть первое место, чтобы проверить.Однако itertools.groupby, безусловно, один из самых сложных itertools, потому что у него есть некоторые возможные подводные камни:

  • Это только группы предметов, если их key -result одинакова для последовательных элементов:

    from itertools import groupby 
    
    for key, group in groupby([1,1,1,1,5,1,1,1,1,4]): 
        print(key, list(group)) 
    # 1 [1, 1, 1, 1] 
    # 5 [5] 
    # 1 [1, 1, 1, 1] 
    # 4 [4] 
    

    Можно использовать sorted раньше - если вы хотите сделать общий groupby.

  • Он дает два элемента, а второй - генератор (так что нужно перебирать второй элемент!). Мне явно нужно было отнести их к list в предыдущем примере.

  • Второй элемент дали отбрасывается, если один продвигает groupby -iterator:

    it = groupby([1,1,1,1,5,1,1,1,1,4]) 
    key1, group1 = next(it) 
    key2, group2 = next(it) 
    print(key1, list(group1)) 
    # 1 [] 
    

    Даже если group1 не пусто!

Как уже упоминалось, можно использовать sorted сделать общую groupby операцию, но это экстремально неэффективен (и выбрасывает памяти к.п.д., если вы хотите использовать GroupBy генераторы). Есть лучшие альтернативы Avaiable, если вы не можете garantuee, что вход sorted (которые также не требуют O(n log(n) сортировки накладных расходов времени):

Однако, это замечательно проверять местные объекты. Есть два рецепта в itertools-recipes section:

def all_equal(iterable): 
    "Returns True if all the elements are equal to each other" 
    g = groupby(iterable) 
    return next(g, True) and not next(g, False) 

и:

def unique_justseen(iterable, key=None): 
    "List unique elements, preserving order. Remember only the element just seen." 
    # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B 
    # unique_justseen('ABBCcAD', str.lower) --> A B C A D 
    return map(next, map(itemgetter(1), groupby(iterable, key))) 
+0

Спасибо. Я обязательно замечу, если мне понадобится какая-то альтернатива. На данный момент я читаю раздел разделов по разделам, чтобы не перебирать все. И счастливый новый год для вас – Parousia