Как разделить список строк по символам в Python

У меня есть список строк, как это:

org_list = ['', '<dialog xyz', 'string', 'more string', 'even more string etc', 
        '<dialog xyz', 'string', 'more string', 'even more string etc']

Мне нужно разделить список на подсписки строк, разделив их точно на '<' символ, так что каждый список строк начинается с 'dialog xyz', Образец вывода:

[['<dialog xyz', 'string', 'more string', 'even more string etc'], ['<dialog 
  xyz', 'string', 'more string', 'even more string etc']]

Я уже пытался понять список, но он не работает (возвращает то же самое org_list):

divided_list = [s.split(',') for s in ','.join(org_list).split('<')]

Я знаю, что это возможно с itertools (видел это в некоторых ответах), но я все еще новичок, не очень понимаю их и хотел бы решить это с тем, что я понимаю, если это возможно.

8 ответов

Сначала мы можем создать list из indexes ссылаясь на позиции в org_list где строка в этой позиции начинается с '<',

Затем мы можем перебрать их в list-comp принятие slices между каждой парой indexes,

Тем не менее, в конце мы заметили, что последний slice должен идти до конца org_listпоэтому мы должны объединить list содержащий индекс один за концом, чтобы захватить это.

Надеюсь, вы сможете увидеть, как это описание переходит в следующий код.

inds = [i for i, s in enumerate(org_list) if '<' in s] + [len(org_list)]
div_l = [org_list[inds[i]:inds[i+1]] for i in range(len(inds)-1)]

который дает желаемый результат:

[['<dialog xyz', 'string', 'more string', 'even more string etc'],
 ['<dialog xyz', 'string', 'more string', 'even more string etc']]

Как насчет чего-то простого:

org_list = ['', '<dialog xyz', 'string', 'more string', 'even more string etc', '<dialog xyz', 'string', 'more string', 'even more string etc']
split_lists = [] 
for s in org_list:
  if s == '':
    continue
  if s.startswith('<') or len(split_lists) == 0: 
    split_lists.append([s])
    continue
  split_lists[-1].append(s)

print(split_lists)

Выход:

[['<dialog xyz', 'string', 'more string', 'even more string etc'], ['<dialog xyz', 'string', 'more string', 'even more string etc']]
org_list = ['', '<dialog xyz', 'ztring', 'more ztring', 'even more string etc', '<dialog xyz', 'string', 'more string', 'even more string etc']

orig = []
start = False

new = []

for item in org_list:
    if item == '<dialog xyz' or item == org_list[-1]:
        if len(new) > 1:
            orig.append(new)
        new = []
        start = True
    if start:
        new.append(item)

print(orig)

Это дает мне вывод, который вы хотите.

Это должно работать:

split_lists = []
for s in org_list:
    if s.startswith('<') or len(split_lists) == 0:
        split_lists.append([])
    split_lists[-1].append(s)

Вот результат для вашего ввода:

>>> split_lists
[[''], ['<dialog xyz', 'string', 'more string', 'even more string etc'], ['<dialog xyz', 'string', 'more string', 'even more string etc']]

Если вы хотите игнорировать все строки перед первой строкой, которая начинается с '<', как пустая строка, которая является первым элементом в вашем org_list, затем используйте это:

split_lists = []
for s in org_list:
    if s.startswith('<'):
        split_lists.append([])
    if len(split_lists) == 0:
        continue
    split_lists[-1].append(s)

Ты можешь использовать itertools.groupby:

import itertools
import re
org_list = ['', '<dialog xyz', 'string', 'more string', 'even more string etc', 
    '<dialog xyz', 'string', 'more string', 'even more string etc']
new_list = [list(b) for a, b in itertools.groupby(filter(None, org_list), key=lambda x:bool(re.findall('^\<dialog', x)))]
final_list = [new_list[i]+new_list[i+1] for i in range(0, len(new_list), 2)]

Выход:

[['<dialog xyz', 'string', 'more string', 'even more string etc'], ['<dialog xyz', 'string', 'more string', 'even more string etc']]

Это может помочь

org_list = ['', '<dialog xyz', 'string', 'more string', 'even more string etc',
        '<dialog xyz', 'string', 'more string', 'even more string etc']

result = [i.split("|") if i.startswith("<") else ("<"+i).split("|") for i in "|".join(filter(None, org_list)).split("|<")]
print result

Выход:

[['<dialog xyz', 'string', 'more string', 'even more string etc'], ['<dialog xyz', 'string', 'more string', 'even more string etc']]

Вы можете сделать что-то вроде этого:

org_list = ['', '<dialog xyz', 'string', 'more string', 'even more string etc',
        '<dialog xyz', 'string', 'more string', 'even more string etc']



flag=True
sub_list=[]
final_list=[]
text='<dialog xyz'
for i in org_list:
    if i.startswith(text):


        flag=False

        if sub_list:
            sub_list.insert(0,text)
            final_list.append(sub_list)

            sub_list=[]

    else:
        if flag==False:



            sub_list.append(i)
sub_list.insert(0,text)
final_list.append(sub_list)
print(final_list)

выход:

[['<dialog xyz', 'string', 'more string', 'even more string etc'], ['<dialog xyz', 'string', 'more string', 'even more string etc']]

Фотоконкурс. Кто сделает функцию более сложной и медленной? Проще говоря, это Python.

org_list = ['', '<dialog xyz', 'string', 'more string', 'even more string etc', 
        '<dialog xyz', 'string', '', 'even more string etc' , '<dialog xyz', 'string', 'more string',]

def slicelist (pred, iterable):
    element = []
    alw = False
    for s in iterable:
         sw = s.startswith
         if sw(pred):
                element.append([])
                alw=True
         if alw :        
                element[-1].append(s)
    return element

print slicelist('<', org_list)

Если вы хотите сделать генератор (итератор), вам нужно изменить следующие операторы в приведенном выше примере: return в yield а также print slicelist('<', org_list) в print list(slicelist('<', org_list))

Другие вопросы по тегам