Уведомления

Группа в Telegram: @pythonsu

#1 Май 5, 2018 13:16:46

SomethingButNotNickName
Зарегистрирован: 2017-12-19
Сообщения: 75
Репутация: +  0  -
Профиль   Отправить e-mail  

модуль itertools

Добрый день.
Есть список списков. Вложенный список всегда из двух элементов, вложенные списки могут повторяться, например:

 lst = [[1, 12],
        [1, 12],
        [3, 32],
        [2, 22],
        [3, 32],
        [2, 22]]
Задача:
1) удалить повторяющиеся элементы;
2) отсортировать по первому элементу вложенного списка.
Сортировку решил так:
 lst.sort(key=lambda x: x[0])
Насчет удаления повторяющихся элементов. Нашел в нете такой вариант:
 from itertools import groupby
new_lst = [el for el, _ in groupby(lst)]
Все работает как задумано, но совершенно не понятно.
el for el - цикл сам по себе?
Запятая и нижнее подчеркивание - что за магия?
Кто может подробно объяснить что происходит при применении данной команды.

Офлайн

#2 Май 5, 2018 13:50:25

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

модуль itertools

SomethingButNotNickName
Запятая и нижнее подчеркивание - что за магия?
1. никакой магии - нижнее подчеркивание это валидное имя переменной
2. Этот алгоритм неправильный. Не будут удалены идущие не подряд одинаковые элементы.



Офлайн

#3 Май 5, 2018 13:53:18

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

модуль itertools

это списковое выражение ( list comprehention)
символ _ никакая ни магия, а такое же имя переменной как a или value, но с тем отличием что оно общепринятое, его используют тогда, когда надо присвоить переменной значение, но сама переменная не нужна. Пример

 l = [0, 1]
a, b = l   # 1
a, _ = l   # 2
Представим что нужно раскрыть список и передать значения в переменные, но интересует нас только значение которое запишется в переменную a. Можно сделать как в случае 1, но тогда linter скажет что задается переменная которая не используется. В случае 2 этого не будет. Однако и в переменную a и в переменную b запишется свое значение.
То есть все это для наглядности, читаемости и удобства.
Несколько более весомые пример в питоне 3
 >>> l = list(range(10))
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a, _, c = l
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)
>>> a, *_, c = l
>>> a, _, c
(0, [1, 2, 3, 4, 5, 6, 7, 8], 9)

Далее, запятая тоже никакая ни магия и можно записать так
 new_lst = [el for (el, _) in groupby(lst)]

Что полностью удовлетворяет сигнатуре вида
 [a for b in c]



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#4 Май 5, 2018 13:56:34

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

модуль itertools

SomethingButNotNickName
Задача:
1) удалить повторяющиеся элементы;
2) отсортировать по первому элементу вложенного списка.
тут надо поменять местами пункты
1.сортировка
2.группировка

Офлайн

#5 Май 5, 2018 15:04:56

SomethingButNotNickName
Зарегистрирован: 2017-12-19
Сообщения: 75
Репутация: +  0  -
Профиль   Отправить e-mail  

модуль itertools

Итак по порядку. Поправьте где не прав.
1) квадратные скобки вокруг всей конструкции справа - генератор списка. Т.е. каждый элемент el который он вернет, будет записан в список new_lst
2) groupby(lst) - создает некий итератор, содержащий элементы исходного lst, но разбитые по группам в соответствии с переданной в groupby() функцией. Т.е. res = groupby(lst) это список кортежей вида (элемент исходного списка, itertools._grouper object). Причем, если подряд идут два одинаковых вложенных списка, дубликаты не включаются.
3) запускается цикл в котором из groupby() вынимается каждый кортеж в виде (el, _).
4) берется значение el и пишется в new_list. Значение _ теряется.

Суть верно изложил?
и если да, то остаются вопросы:
1) что такое itertools._grouper object и его назначение.
2) Как было верно подмечено данный алгоритм не удаляет дубликаты идущие не подряд. groupby можно использовать только с предварительно отсортированными массивами ( и для не сортированных нужен другой метод) или можно отредактировать мой код?

Офлайн

#6 Май 5, 2018 15:33:53

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

модуль itertools

SomethingButNotNickName
1) что такое itertools._grouper object и его назначение.
  
>>> import itertools
>>> 
>>> it = itertools.groupby('abbccc')
>>> 
>>> elem = next(it)
>>> elem
('a', <itertools._grouper object at 0x7f53b0bad780>)
>>> list(elem[1])
['a']
>>> 
>>> elem = next(it)
>>> elem
('b', <itertools._grouper object at 0x7f53b0bad7f0>)
>>> list(elem[1])
['b', 'b']
>>> 
>>> elem = next(it)
>>> elem
('c', <itertools._grouper object at 0x7f53b0bad7b8>)
>>> list(elem[1])
['c', 'c', 'c']
>>>



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version