Как мне разделить строку с несколькими разделителями, но только один раз на каждом разделителе? Python

#python #split #csv

#python #разделить #csv

Вопрос:

Я пытаюсь разделить строку, такую как приведенная ниже, со всеми разделителями ниже, но только один раз.

string = 'it; seems; liketa goodtday to watchvavmovie.'

delimiters = 't v ;'

В этом случае вывод будет:

['it', ' seems; like', 'a goodtday to watch', 'avmovie.']

Очевидно, что приведенный выше пример является бессмысленным примером, но я пытаюсь узнать, возможно ли это. Будет ли в порядке достаточно сложное регулярное выражение?

Извиняюсь, если этот вопрос был задан раньше. Я немного поискал и не смог найти что-то похожее на мой пример. Спасибо за ваше время!

Ответ №1:

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

 import re

def split_once_by(s, delims):
    delims = set(delims)
    parts = []
    while delims:
        delim_re = '({})'.format('|'.join(re.escape(d) for d in delims))
        result = re.split(delim_re, s, maxsplit=1)
        if len(result) == 3:
            first, delim, s = result
            parts.append(first)
            delims.remove(delim)
        else:
            break
    
    parts.append(s)
    return parts
 

Пример:

 >>> split_once_by('it; seems; liketa goodtday to watchvavmovie.', 'tv;')
['it', ' seems; like', 'a goodtday to watch', 'ax0bmovie.']
 

Ответ Burning Alcohol вдохновил меня на написание этой (IMO) лучшей функции:

 def split_once_by(s, delims):
    split_points = sorted((s.find(d), -len(d), d) for d in delims)
    start = 0
    for stop, _longest_first, d in split_points:
        if stop < start: continue
        yield s[start:stop]
        start = stop   len(d)
    yield s[start:]
 

с использованием:

 >>> list(split_once_by('it; seems; liketa goodtday to watchvavmovie.', 'tv;'))
['it', ' seems; like', 'a goodtday to watch', 'ax0bmovie.']
 

Комментарии:

1. Спасибо; это было полезно, и я ценю, что вы снова повторяете процесс, чтобы придумать другой ответ.

2. Поддержал этот ответ, поскольку он использует меньше памяти, но логика @orlp и моя должна быть одинаковой. Рад, что мой ответ может вдохновить на обсуждение!

Ответ №2:

Простой алгоритм будет делать,

 test_string = r'it; seems; liketa goodtday to watchvavmovie.'

delimiters = [r't', r'v', ';']

# find the index of each first occurence and sort it
delimiters = sorted(delimiters, key=lambda delimiter: test_string.find(delimiter))

splitted_string = [test_string]

# perform split with option maxsplit
for index, delimiter in enumerate(delimiters):
    if delimiter in splitted_string[-1]:
        splitted_string  = splitted_string[-1].split(delimiter, maxsplit=1)
        splitted_string.pop(index)

print(splitted_string)
# ['it', ' seems; like', 'a good\tday to watch', 'a\vmovie.']
 

Ответ №3:

Просто создайте список шаблонов и примените их один раз:

 string = 'it; seems; liketa goodtday to watchvavmovie.'
patterns = ['t', 'v', ';']

for pattern in patterns:
    string = '*****'.join(string.split(pattern, maxsplit=1)) 

print(string.split('*****'))
 

Вывод:

 ['it', ' seems; like', 'a goodtday to watch', 'ax0bmovie.']
 

Итак, что это "*****" ??

На каждой итерации, когда вы применяете split метод, вы получаете список. Итак, на следующей итерации вы не сможете применить .split () метод (потому что у вас есть список), поэтому вам нужно объединить каждое значение этого списка с каким-нибудь странным символом, например "****" , или "@@@" или "^^^^^^^" или что угодно, чтобы повторно применить split () на следующей итерации. Наконец, для каждой "*****" вашей строки у вас будет один шаблон списка, так что вы можете использовать это для окончательного разделения.

Комментарии:

1. Что, если входные данные содержат ***** ?

2. на каждой итерации, когда вы применяете разделение, вы получаете список. Итак, на следующей итерации я не могу применить .split() (потому что у меня есть список), поэтому я присоединяюсь к этому списку с каким-то странным символом, таким как «****», чтобы повторно применить метод split()

3. Вы не ответили на мой вопрос. Что делать, если входная строка содержит **** или что вы выберете как «что-то странное»?

4. Я привел пример, чтобы прояснить свой ответ.

5. Я понимаю ваш ответ, мой вопрос является педагогическим, чтобы попытаться заставить вас осознать проблему с вашим ответом.