Интересная/дурацкая задача на питоне

Dec 22, 2019 20:32

Задача: написать этот код идиоматически.

Суть проблемы: формат такой: строка, начинающаяся не с пробела - начало записи. Дальше сколько-то строк, начинающихся с пробелов, относящихся к этой же самой записи.

Т.е.

foo foobar
bar
bar
next foobar
bar
etc
Задача - распарсить на записи, так, чтобы каждая "запись" была массивом "своих" строк ( ( Read more... )

python

Leave a comment

Comments 32

anonymous December 22 2019, 20:55:57 UTC
Это чтобы вывод ifconfig разложить?

Reply

amarao_san December 23 2019, 13:57:06 UTC
ip

Reply

igann December 23 2019, 21:30:57 UTC
psutils на клиентской машине поставить? Там вроде это все есть и еще до фига чего.

Reply

amarao_san December 24 2019, 09:46:26 UTC
Это внутри кода для ансиблового модуля. Я думал использовать netlink (нативный протокол с ядром), но тогда бы я этот модуль никогда в жизни не написал. Использовать же внешние библиотеки - чревато, ибо модуль на ремот хосте, чем меньше зависимостей, тем лучше.

https://github.com/amarao/ansible/blob/8eea26b207b5a01c725efc1acce942de0c137c39/lib/ansible/modules/net_tools/ip_link_set.py

Reply


igann December 22 2019, 21:35:12 UTC
Я бы сделал регексп сплитом

Reply

amarao_san December 23 2019, 13:57:49 UTC
Шухерно. Многострочные регэкспы - это какая-то терра инкогнита с драконами.

Reply

igann December 23 2019, 21:20:21 UTC
Ну, как хотите

In [2]: text= '''foo foobar
bar
bar
next foobar
bar
bar
etc
'''
Out[2]:

In [4]: [(block[0], block[1:]) for block in [fragment.splitlines() for fragment in re.split('\n(?=\w)', text)]]
Out[4]:
[('foo foobar', [' bar', ' bar']),
('next foobar', [' bar', ' bar']),
('etc', [])]

(код для иллюстрации)

Reply

igann December 23 2019, 21:56:16 UTC
Потестил на ipconfig вроде сюрпризов не видно в первом приближении

In [16]: import json ( ... )

Reply


aklepatc December 23 2019, 18:54:24 UTC
как-то так:

iterable = (line for line in raw_output.split(‘\n’) if line)
def children():
for child in iterable:
if child[0] != ‘ ‘:
children.parent = child
return
yield child
children.parent = None
children.parent = next(iterable, None)
while children.parent is not None:
yield children.parent, children()

Reply

amarao_san December 24 2019, 09:55:05 UTC
11 строк вместо 12, и я очень не понял children.parent. Это ты объект "функция" дописываешь своё?

Reply

aklepatc December 25 2019, 00:28:04 UTC
Функция в Питоне - объект. И у неё могут быть атрибуты/свойства как любово объекта. А так - всё верно, это не намного лучше, чем ваше первоначальное решение

Reply

aklepatc December 25 2019, 00:31:42 UTC
Мне сейчас больше нравится моя вторая версия ниже (если оно, конечно, работает - я не тестировал). Но вообще, ваш первоначальный код вполне норм

Reply


aklepatc December 23 2019, 22:52:00 UTC
это некоторый хак, но тоже должно сработать:

from itertools import groupby
iterable = (line for line in raw_input.split('\n') if line)
def key_func(line):
if line[0] != ' ':
key_func.state = not key_func.state
return key_func.state
key_func.state = True
result = (group for _, group in groupby(iterable, key=key_func))
семантика, кстати, ближе к вашему первоначальному коду.

Reply


anonymous December 24 2019, 00:42:01 UTC
На питоне не пишу, и без понятия что за рекорды, т/к это питон, очевидно, код из поста не запустился. Поэтому догадаться не получилось.

Вот вариация на массивах

>>> test="""foo foobar
... bar
... bar
... next bar
... bar
... end"""
>>> def join(acc, line): return (acc[-1].append(line) if line.startswith(' ') else acc.append([line])) or acc
...
>>> import functools
>>> functools.reduce(join, test.split('\n'), [])
[['foo foobar', ' bar', ' bar'], ['next bar', ' bar'], ['end']]

Reply

amarao_san December 24 2019, 09:53:14 UTC
На
or acc мой мозг возмутился. Понятно, но всё равно WTF. Не питонически.

Reply


Leave a comment

Up