Задать вопрос

Полная ли жесть данный код на python?

Как-то однажды нужно было написать конвертацию одного списка в другой:
[('www.ya.ru', set()), ('ya.ru', set()), ('xxx.x', set())]

И нужно из этого получить список с доменами без www, где множества, находящиеся с ними в одном tuple, объедены: [('ya.ru', set()), ('xxx.x', set())]
Писать, как это решить обычно и просто, думаю, смысла нет. Но в тот момент я находился в интерактивном питоне и писал, что идет в голову. В итоге родился ад, который лично мне не наносит никакой боли, хотя я не уверен, что это нельзя сделать проще. Скорее всего, можно, но я этим не занимался.
resolved = reduce(lambda x, y: x[:-1]+[(y[0][0], y[0][1].union(x[-1][1]))] if x[-1][0]==y[0][0] else x+y, sorted([[(i[0].split('www.')[-1], i[1])] for i in resolved]))

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

Оговорюсь, что я считаю, что этот код не по философии питона, его вряд ли можно назвать хорошим. Но, гипотетически, его появление с комментом о том, что он делает, - это не слишком печально для остальных разработчиков? Или лучше не заниматься подобными функциональными изысками? Что бы вы подумали о человеке, который это написал и оставил после рефакторинга?

p.s. Если кто-то решил использовать что-либо из примера выше, настоятельно не рекомендую, так как он содержит баг и, вообще, не крутой. Крутой пример для этой же задачи есть в комментариях.

С учетом этого суть вопроса топика может быть изложена иначе: жесть ли переписывать маленькие/самодостаточные алгоритмы в функциональный стиль (при наличии адекватного оформления кода и пояснений) внутри императивной программы?
  • Вопрос задан
  • 2556 просмотров
Подписаться 3 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 6
@zedxxx
Жесть полная. Пишите код для людей.
Ответ написан
Комментировать
Rrooom
@Rrooom
Нормально. Главное не забывайте всё логично разбить на строки.
Ответ написан
vvpoloskin
@vvpoloskin
Инженер связи
Если все в одну строчку и без доки, то херово. Если бы задача упала, удалил бы эту строку и написал заново.
Ответ написан
Комментировать
yttrium
@yttrium
'У кого длинее'
reduce(lambda x,y: (x[0],x[0].__setitem__(y[0],x[0][y[0]].union(y[1]))),map(lambda x:(re.match(r'(www\.)?(.*)',x[0]).group(2),x[1]),l),(defaultdict(set),))[0].items()

Функциональный подход. если вынести re.compile должно быть быстрее
Ответ написан
@VovanZ
Я бы отформатировал его, хотя бы как-то так:
resolved = reduce(
    lambda x, y: x[:-1]+[(y[0][0], y[0][1].union(x[-1][1]))] if x[-1][0]==y[0][0] else x+y, 
    sorted(
        [[(i[0].split('www.')[-1], i[1])] for i in resolved]
    )
)
Ответ написан
Комментировать
adugin
@adugin Куратор тега Python
Лютый говнокодище - что у автора, что в комментах :)
dlist = [('www.ya.ru', {1,2,3}), ('ya.ru', {4,5}), ('xxx.x', {6,7,8,9})]

Если порядок элементов не важен, то эталонный код должен выглядеть так:
from collections import defaultdict

buffer = defaultdict(set)
for domain, stuff in dlist:
    buffer[domain.lstrip('www.')].update(stuff)
print buffer.items()

Если порядок важен:
from collections import OrderedDict

buffer = OrderedDict()
for domain, stuff in dlist:
    if domain.startswith('www.'):
        domain = domain[4:]
    buffer.setdefault(domain, set()).update(stuff)
print buffer.items()

И не надо лепить нечитабельные однострочники! Но если ради научного интереса:
buffer = defaultdict(set)
map(lambda (domain, stuff): buffer[domain.lstrip('www.')].update(stuff), dlist)
print buffer.items()

Или так:
reduce(
    lambda buffer, (domain, stuff): buffer[domain.lstrip('www.')].update(stuff) or buffer,
    dlist,
    defaultdict(set)
).items()
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы