Подтвердить что ты не робот

Разделить строку при n-м вхождении заданного символа

Есть ли способ Python для разделения строки после n-го вхождения данного разделителя?

С учетом строки:

'20_231_myString_234'

Его следует разбить на (с разделителем, являющимся "_", после его второго появления):

['20_231', 'myString_234']

Или это единственный способ сделать это для подсчета, разделения и присоединения?

4b9b3361

Ответ 1

>>> n = 2
>>> groups = text.split('_')
>>> '_'.join(groups[:n]), '_'.join(groups[n:])
('20_231', 'myString_234')

Похоже, что это наиболее читаемый способ, альтернативой является регулярное выражение)

Ответ 2

Используя re, чтобы получить регулярное выражение формы ^((?:[^_]*_){n-1}[^_]*)_(.*), где n - переменная:

n=2
s='20_231_myString_234'
m=re.match(r'^((?:[^_]*_){%d}[^_]*)_(.*)' % (n-1), s)
if m: print m.groups()

или иметь приятную функцию:

import re
def nthofchar(s, c, n):
    regex=r'^((?:[^%c]*%c){%d}[^%c]*)%c(.*)' % (c,c,n-1,c,c)
    l = ()
    m = re.match(regex, s)
    if m: l = m.groups()
    return l

s='20_231_myString_234'
print nthofchar(s, '_', 2)

Или без регулярных выражений, используя итеративную находку:

def nth_split(s, delim, n): 
    p, c = -1, 0
    while c < n:  
        p = s.index(delim, p + 1)
        c += 1
    return s[:p], s[p + 1:] 

s1, s2 = nth_split('20_231_myString_234', '_', 2)
print s1, ":", s2

Ответ 3

Мне нравится это решение, потому что оно работает без какого-либо экстренного регулярного выражения и может быть легко адаптировано к другому "nth" или разделителю.

import re

string = "20_231_myString_234"
occur = 2  # on which occourence you want to split

indices = [x.start() for x in re.finditer("_", string)]
part1 = string[0:indices[occur-1]]
part2 = string[indices[occur-1]+1:]

print (part1, ' ', part2)

Ответ 4

Я думал, что внес мои два цента. Второй параметр split() позволяет ограничить разделение после определенного количества строк:

def split_at(s, delim, n):
    r = s.split(delim, n)[n]
    return s[:-len(r)-len(delim)], r

На моей машине два хороших ответа от @perreal, итеративная находка и регулярные выражения на самом деле измеряют в 1,4 и 1,6 раза медленнее (соответственно), чем этот метод.

Стоит отметить, что он может стать еще быстрее, если вам не нужен начальный бит. Затем код становится:

def remove_head_parts(s, delim, n):
    return s.split(delim, n)[n]
Я не согласен с этим, но он выполняет эту работу. Несколько удивительно, что он в 2 раза быстрее, чем итеративная находка, и в 3 раза быстрее, чем регулярные выражения.

Я выставил мое тестирование script онлайн. Вы можете ознакомиться и прокомментировать.

Ответ 5

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

Ответ 6

>>>import re
>>>str= '20_231_myString_234'

>>> occerence = [m.start() for m in re.finditer('_',str)]  # this will give you a list of '_' position
>>>occerence
[2, 6, 15]
>>>result = [str[:occerence[1]],str[occerence[1]+1:]] # [str[:6],str[7:]]
>>>result
['20_231', 'myString_234']

Ответ 7

У меня была более длинная строка, чтобы разделить любой n-й символ, в итоге появился следующий код:

# Split every 6 spaces
n = 6
sep = ' '
n_split_groups = []

groups = err_str.split(sep)
while len(groups):
    n_split_groups.append(sep.join(groups[:n]))
    groups = groups[n:]

print n_split_groups

Спасибо @perreal!