Разбейте этот список, используя понимание списка - PullRequest
3 голосов
/ 05 марта 2012

Мне было интересно, есть ли хороший питонический способ разбить этот список:

['1,2,3', '22', '33']

в список:

['1','2','3','22','33']

использование списка понимания?

Ответы [ 7 ]

7 голосов
/ 05 марта 2012

С пониманием списка это будет выглядеть так:

>>> L = ['1,2,3', '22', '33']
>>> [x for l in L for x in l.split(",")]
['1', '2', '3', '22', '33']

Примечание: есть более четкие и лучшие способы сделать это, как уже было опубликовано в других ответах (либо цепочка itertools, либо выражение генератора хорошо). Но так как вопрос касается синтаксиса понимания списка, я решил, что все равно скину это.

5 голосов
/ 05 марта 2012

Я бы не стал использовать sum, поскольку он выполняет многократную конкатенацию и создает много копий. Я бы сделал это:

>>> import itertools
>>> l =  ['1,2,3', '22', '33']
>>> list(itertools.chain.from_iterable(s.split(',') for s in l))
['1', '2', '3', '22', '33']

Это правда, что для очень коротких списков это немного медленнее:

>>> %timeit sum((s.split(',') for s in l), [])
100000 loops, best of 3: 2.38 us per loop
>>> %timeit list(itertools.chain.from_iterable(s.split(',') for s in l))
100000 loops, best of 3: 3.51 us per loop

Но для длинных списков это способ быстрее, чем sum:

>>> l =  ['1,2,3', '22', '33'] * 500
>>> %timeit sum((s.split(',') for s in l), [])
100 loops, best of 3: 6.22 ms per loop
>>> %timeit list(itertools.chain.from_iterable(s.split(',') for s in l))
1000 loops, best of 3: 664 us per loop

На самом деле, мне скорее нравится wim ответ. И быстрый тест показывает, что это самая быстрая во всех случаях загрузка:

>>> l =  ['1,2,3', '22', '33'] 
>>> %timeit [x for s in l for x in s.split()]
1000000 loops, best of 3: 1.45 us per loop
>>> l =  ['1,2,3', '22', '33'] * 500
>>> %timeit [x for s in l for x in s.split()]
1000 loops, best of 3: 559 us per loop
5 голосов
/ 05 марта 2012

Поскольку уже было опубликовано два ответа с использованием функции sum() в качестве решения, я подумал, что могу внести еще один способ, используя itertools.chain

from itertools import chain
x = ['1,2,3', '22', '33']
result = chain.from_iterable(i.split(',') for i in x)

print result
#<itertools.chain object at 0x1004b5e10>

Результатом команды chain являетсягенератор.Таким образом, вы можете перебрать результат или привести его к другому типу последовательности (tuple, list, set, ...)

3 голосов
/ 05 марта 2012

Разбей свою проблему. Вы никогда не сможете увидеть, как решить всю проблему за один раз, а в Python никогда не было простых встроенных решений для целых проблем. Выясните, каковы основные части вашей проблемы, и часто есть простые прямые решения для каждой части. Затем объедините решения. Кроме того, не ожидайте, что вы можете взмахнуть волшебной ключевой фразой, такой как «понимание списка», для устранения проблемы. Выясните, что нужно сделать вашему решению, а затем подумайте, может ли это сделать понимание списков.

У вас есть строка '1,2,3'. Вам нужно разделить это на список из нескольких строк, содержащий биты исходной строки, разделенные запятыми:

>>> help(str.split)
Help on method_descriptor:

split(...)
    S.split([sep [,maxsplit]]) -> list of strings

    Return a list of the words in the string S, using sep as the
    delimiter string.  If maxsplit is given, at most maxsplit
    splits are done. If sep is not specified or is None, any
    whitespace string is a separator and empty strings are removed
    from the result.

>>> '1,2,3'.split(',')
['1', '2', '3']
>>> '3'.split(',')
['3']

Теперь у вас есть список строк, и вы хотите разделить каждую из них на список, как указано выше:

>>> [s.split(',') for s in ['1','2','3','22','33']]
[['1'], ['2'], ['3'], ['22'], ['33']]

Теперь у вас есть список списков. Вы хотите один список, содержащий элементы каждого из списков в вашем списке списков. Операция «дай мне каждую вещь в каждом из списков в списке списков» довольно естественным образом сопоставляется с пониманием списка следующим образом:

>>> list_of_lists = [[1, 2, 3], ['a', 'b', 'c']]
>>> [thing for alist in list_of_lists for thing in alist]
[1, 2, 3, 'a', 'b', 'c']

Собираем все вместе:

>>> [bit for string in ['1','2','3','22','33'] for bit in string.split(',')]
['1', '2', '3', '22', '33']

Так вот как вы решаете это с помощью списочных представлений. В других ответах есть много других потенциальных решений, которые лучше по техническим причинам. Но если вы новичок в Python, изучать всю стандартную библиотеку (особенно мощные, но абстрактные вещи, такие как itertools) будет сложно, и вам не нужно это делать. Познакомиться с основами поможет вам в долгосрочной перспективе.

2 голосов
/ 05 марта 2012

Это самое простое решение, которое я могу придумать.

Используется sum() с выражением генератора, поскольку вам не нужно сохранять созданные подсписки.

>>> a = ['1,2,3', '22', '33']
>>> sum((s.split(',') for s in a), [])
['1', '2', '3', '22', '33']
1 голос
/ 05 марта 2012

Простой способ сделать это:

>>> lst = ['1,2,3', '22', '33']
>>> res = []
>>> for x in lst:
...     res.extend(x.split(','))
>>> res
['1', '2', '3', '22', '33']

Хотя он не использует понимание списка, но я не понимаю, почему вы бы использовали его в этом случае.

1 голос
/ 05 марта 2012

Вы можете сделать что-то вроде этого (предположим, ваш список называется l):

sum([s.split(',') for s in l], [])
...