У меня есть список, который выглядит примерно так:
data = ['1', '12', '123']
Я хочу создать новый список, который выглядит так:
result = ['$1', '1', '$2', '12', '$3', '123']
где число после знака $
— это длина следующего элемента.
Самый простой способ сделать это — использовать цикл for
:
result = []
for element in data:
result += [f'${len(element)}'] + [element]
но мне было интересно, можно ли сделать это более элегантным способом - возможно, с помощью понимания списка?
я мог бы сделать
result = [[f'${len(e)}', e] for e in data]
но это приводит к списку списков:
[['$1', '1'], ['$2', '12'], ['$3', '123']]
Я мог бы сгладить это с помощью чего-то вроде
result = sum([[f'${len(e)}', e] for e in data], [])
или даже
result = [x for xs in [[f'${len(e)}', e] for e in data] for x in xs]
но это становится довольно трудно читать. Есть лучший способ сделать это?
Нет необходимости использовать понимание списка, если это явно ухудшает читаемость.
Просто используйте способ, который вы упомянули:
for element in data:
result += [f'${len(element)}', element]
Понимание списка просто не предназначено для использования для таких задач.
Одним из возможных решений является использование chain
из itertools
:
from itertools import chain
result = list(chain(*[[f'${len(e)}', e] for e in data]))
Отличный ответ, но вы можете избежать внутреннего списка, поскольку chain
будет потреблять генераторы: result = list(chain(*([f'${len(e)}', e] for e in data)))
.
@tdelaney chain
не потребляет ваш генератор. *
да. chain
даже не знает, что это произошло.
Вы можете сделать это с помощью двух циклов:
result = [item for s in data for item in (f"${len(s)}", s)]
['$1', '1', '$2', '12', '$3', '123']
Опереди меня на 6 минут.
@e-motta, Ницца, и я проголосовал за. Пожалуйста, посмотрите мое решение с одним циклом.
>>> data = ['1', '12', '123']
>>> [x for d in data for x in [f"${len(d)}", d]]
['$1', '1', '$2', '12', '$3', '123']
Добавляю сюда свою попытку:
result = [f"${len(e)}" if i == 0 else e for e in data for i in range(0,2)]
если то, что вы подразумеваете под элегантностью, является однострочным, это решение и с одним циклом
r = [f'${len(data[int(x/2)])}' if x%2==0 else data[int(x/2)] for x in range(2*len(data))]
что эквивалентно
r = []
for x in range(2*len(data)):
if x % 2 == 0: r.append(f'${len(data[int(x/2)]))
else: r.append(data[int(x/2)])
Вот еще один лайнер:
data = ['1', '12', '123']
list(sum([(f"${len(x)}",x) for x in data[:]], ()))
# ['$1', '1', '$2', '12', '$3', '123']
Мне интересно, какое решение из ответов самое быстрое.