Здравствуйте!
Подскажите, пожалуйста, как можно разбить уловный список ['1', '22', '333'] по символам, т.е. чтобы получился список ['1', '2', '2', '3', '3', '3']
Заранее спасибо!
Ответ
На функциональщине в одну строчку:
reduce(lambda a, x: a + x, map(lambda x: list(x), ['1', '22', '333']))
Поясняю - reduce принимает на вход функцию, которая объединяет результаты разбиения списка функцией map. Map принимает на вход функцию и начальный массив, над каждым элементом массива выполняется данная функция. То же самое можно выразить следующим кодом:
>>> result_list = []
>>> for x in ['1', '22', '333']:
... for y in list(x):
... result_list.append(y)
...
>>> print(result_list)
['1', '2', '2', '3', '3', '3']
Сравнение по скорости предложенных вариантов:
Вариант с использованием join и объединением в строку результата уделал всех. Оно и неудивительно — все операции здесь быстрые. Будет работать с любыми iterable объектами:
$python3 -m timeit "list(''.join(['1', '22', '333']))"
1000000 loops, best of 3: 0.318 usec per loop
Вариант с использованием генератора списка из ответа @jfs действительно работает быстро:
$python3 -m timeit "[char for s in ['1', '22', '333'] for char in s]"
1000000 loops, best of 3: 0.452 usec per loop
Вариант с использованием sum занимает третье место по скорости, однако по моему мнению, проигрывает в интуитивности:
$python3 -m timeit "sum([list(i) for i in ['1', '22', '333']], [])"
1000000 loops, best of 3: 0.984 usec per loop
Вариант на map-reduce является самым медленным. Почему я его использую? Потому что мне нравятся цепочки вызовов. Остальное — вкусовщина. Однако даже Гвидо ненавидит reduce (и вынес его в functools в python3)
$python3 -m timeit "from functools import reduce; reduce(lambda a, x: a + x, map(lambda x: list(x), ['1', '22', '333']))"
100000 loops, best of 3: 2.16 usec per loop
Вариант с collections покрывает все случаи, когда передаваемый объект может быть неитерируемым (число, например), однако цена за такое — большое время выполнения:
$python3 -m timeit "import collections
def it(obj):
if isinstance(obj, collections.Iterable):
for ob in obj:
if isinstance(ob, collections.Iterable) and len(ob) > 1:
yield from it(ob)
else: yield ob
else:
yield obj
list(it(['1', 2, [2, 44, '123', ('qwe')], 2]))"
100000 loops, best of 3: 14.6 usec per loop
Комментариев нет:
Отправить комментарий