Как разбить список строк на строки подстроки на определенный строковый элемент
У меня есть список слов, как показано ниже. Я хочу разбить список на .
. Есть ли лучший или полезный код в Python 3?
a = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.']
result = []
tmp = []
for elm in a:
if elm is not '.':
tmp.append(elm)
else:
result.append(tmp)
tmp = []
print(result)
# result: [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
Update
Добавьте тестовые примеры для правильной обработки.
a = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.']
b = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.', 'yes']
c = ['.', 'this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.', 'yes']
def split_list(list_data, split_word='.'):
result = []
sub_data = []
for elm in list_data:
if elm is not split_word:
sub_data.append(elm)
else:
if len(sub_data) != 0:
result.append(sub_data)
sub_data = []
if len(sub_data) != 0:
result.append(sub_data)
return result
print(split_list(a)) # [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
print(split_list(b)) # [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice'], ['yes']]
print(split_list(c)) # [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice'], ['yes']]
Ответы
Ответ 1
Используя itertools.groupby
from itertools import groupby
a = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.']
result = [list(g) for k,g in groupby(a,lambda x:x=='.') if not k]
print (result)
#[['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
Ответ 2
Вы можете сделать все это с помощью "однострочного", используя функции подсчета списков и строковые функции join
, split
, strip
и никаких дополнительных библиотек.
a = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.']
b = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.', 'yes']
c = ['.', 'this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.', 'yes']
In [5]: [i.strip().split(' ') for i in ' '.join(a).split('.') if len(i) > 0 ]
Out[5]: [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
In [8]: [i.strip().split(' ') for i in ' '.join(b).split('.') if len(i) > 0 ]
Out[8]: [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice'], ['yes']]
In [9]: In [8]: [i.strip().split(' ') for i in ' '.join(c).split('.') if len(i) > 0 ]
Out[9]: [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice'], ['yes']]
@Craig имеет более простое обновление:
[s.split() for s in ' '.join(a).split('.') if s]
Ответ 3
Здесь другой способ использования только стандартных операций с списком (без зависимостей от других библиотек!). Сначала мы находим точки разделения, а затем создаем подсписки вокруг них; обратите внимание, что первый элемент рассматривается как частный случай:
a = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.']
indexes = [-1] + [i for i, x in enumerate(a) if x == '.']
[a[indexes[i]+1:indexes[i+1]] for i in range(len(indexes)-1)]
=> [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
Ответ 4
Вы можете восстановить строку с помощью ' '.join
и использовать regex:
import re
a = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.']
new_s = [b for b in [re.split('\s', i) for i in re.split('\s*\.\s*', ' '.join(a))] if all(b)]
Вывод:
[['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
Ответ 5
Я не мог с собой поделать, просто хотел повеселиться с этим великим вопросом:
import itertools
a = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.']
b = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.', 'yes']
c = ['.', 'this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.', 'yes']
def split_dots(lst):
dots = [0] + [i+1 for i, e in enumerate(lst) if e == '.']
result = [list(itertools.takewhile(lambda x : x != '.', lst[dot:])) for dot in dots]
return list(filter(lambda x : x, result))
print(split_dots(a)) # [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
print(split_dots(b)) # [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice'], ['yes']]
print(split_dots(c)) # [['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice'], ['yes']]
Ответ 6
Этот ответ требует установки сторонней библиотеки: iteration_utilities
1. Включенная функция split
позволяет легко решить эту задачу:
>>> from iteration_utilities import split
>>> a = ['this', 'is', 'a', 'cat', '.', 'hello', '.', 'she', 'is', 'nice', '.']
>>> list(filter(None, split(a, '.', eq=True)))
[['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
Вместо использования параметра eq
вы также можете определить пользовательскую функцию, где нужно разделить:
>>> list(filter(None, split(a, lambda x: x=='.')))
[['this', 'is', 'a', 'cat'], ['hello'], ['she', 'is', 'nice']]
Если вы хотите сохранить '.'
, вы также можете использовать аргумент keep_before
:
>>> list(filter(None, split(a, '.', eq=True, keep_before=True)))
[['this', 'is', 'a', 'cat', '.'], ['hello', '.'], ['she', 'is', 'nice', '.']]
Обратите внимание, что библиотека просто упрощает работу - легко (см. другие ответы) для выполнения этой задачи без установки дополнительной библиотеки.
filter
можно удалить, если вы не ожидаете, что '.'
появится в начале или конце вашего списка, который будет разбит на разделы.
1 Я автор этой библиотеки. Он доступен через pip
или канал conda-forge
с conda
.