У меня есть этот бит для анализа вывода из стандартного вывода:
out_lines = res.stdout.split("\n")
out_lines = [e.split() for e in out_lines]
out_vals = [{"date":e[0],
"time":e[1],
"size":e[2],
"name":e[3]} for e in out_lines if e]
Есть ли здесь идиоматический способ объединить вторую и третью строки, чтобы разделение и сопоставление происходило внутри одной строки, без избыточных вызовов e.split()
?
Я бы пошел другим путем и добавил вспомогательную функцию (например, my_obj_from_line
), которая выполнила бы разделение и создала новый объект.
Вы можете использовать:
[{"date": e[0], "time": e[1], "size": e[2], "name": e[3]} for e in (line.split() for line in sample_stdout.split("\n")) if e]
Вы можете использовать zip
, чтобы соединить ключи со словами, а затем передать это конструктору dict
.
Тогда, если split()
приведет к появлению пустого списка, вы получите пустые объекты, которые можно будет отфильтровать позже:
out_vals = list(filter(None, (
dict(zip(("date", "time", "size", "name"), line.split()))
for line in res.stdout.split("\n")
)))
Небольшая модификация подхода Тринкота: выделение line.split()
путем привязки имени data
к одноэлементному кортежу и использование if line.strip()
для обращения к пустым строкам, а не использование filter
после этого.
[
dict(zip(("date", "time", "size", "name"), data))
for line in text.splitlines()
if line.strip()
for data in (line.split(),)
]
Ответ @trincot работает, но можно избежать фильтра постобработки, сопоставив строки с str.split
, чтобы вместо этого фильтрацию можно было выполнить с помощью предложения if
понимания:
out_vals = [
dict(zip(("date", "time", "size", "name"), e))
for e in map(str.split, res.stdout.split("\n")) if e
]
Возможно, вы сможете сделать это, используя оператор моржа для хранения результатов
e.split()
, но это будет некрасиво.