Попытка разбить строку под номером 7, и я хочу, чтобы 7 было включено во вторую часть разбитой строки.

Код:

a = 'cats can jump up to 7 times their tail length'

words = a.split("7")

print(words)

Выход:

['cats can jump up to ', ' times their tail length']

Строка раскололась, но вторая часть не включает 7.

Я хочу знать, как я могу включить 7.

Примечание: не дублируйте разделение Python () без удаления разделителя, поскольку разделитель должен быть частью второй строки.

5
Samyak Jain 23 Фев 2018 в 18:07

4 ответа

Лучший ответ

В одной строке, используя re.split с остальной частью строки, и отфильтруйте последнюю пустую строку, которую оставляет re.split:

import re
a = 'cats can jump up to 7 times their tail length'
print([x for x in re.split("(7.*)",a) if x])

Результат:

['cats can jump up to ', '7 times their tail length']

Использование () в регулярном выражении split указывает re.split не сбрасывать разделитель. (7) регулярное выражение сработало бы, но создало бы список из 3 элементов, как str.partition, и потребовало бы некоторой постобработки, так что ни одной строки.

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

[x for x in re.split("(\d.*)",a) if x]
4
Jean-François Fabre 23 Фев 2018 в 16:54

Может также использоваться для глобального захвата:

>>> s = 'The 7 quick brown foxes jumped 7 times over 7 lazy dogs'
>>> sep = '7'
>>> 
>>> [i for i in re.split(f'({sep}[^{sep}]*)', s) if i]
['The ', '7 quick brown foxes jumped ', '7 times over ', '7 lazy dogs']

Если f-строку трудно прочитать, обратите внимание, что она просто оценивается как (7[^7]*).
(С той же целью, что и listcomp, можно использовать list(filter(bool, ...)), но это довольно уродливо)


В Python 3.7 и более поздних версиях re.split() позволяет разбивать шаблоны с нулевой шириной. Это означает, что вместо группы, показанной выше, можно использовать регулярное выражение, а именно f'(?={sep})'.

Что странно в этом, так это время: если использовать re.split() (то есть без объекта скомпилированного шаблона), групповое решение последовательно работает примерно в 1,5 раза быстрее, чем просмотр. Однако при компиляции упреждающий удар превосходит других:

In [4]: r_lookahead = re.compile('f(?={sep})')

In [5]: r_group = re.compile(f'({sep}[^{sep}]*)')

In [6]: %timeit [i for i in r_lookahead.split(s) if i]
2.76 µs ± 207 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [7]: %timeit [i for i in r_group.split(s) if i]
5.74 µs ± 65.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [8]: %timeit [i for i in r_lookahead.split(s * 512) if i]
137 µs ± 1.93 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [9]: %timeit [i for i in r_group.split(s * 512) if i]
1.88 ms ± 18.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Рекурсивное решение также работает нормально, хотя и медленнее, чем разбиение по скомпилированному регулярному выражению (но быстрее, чем прямое re.split(...)):

def splitkeep(s, sep, prefix=''):
    start, delim, end = s.partition(sep)
    return [prefix + start, *(end and splitkeep(end, sep, delim))]
>>> s = 'The 7 quick brown foxes jumped 7 times over 7 lazy dogs'
>>> 
>>> splitkeep(s, '7')
['The ', '7 quick brown foxes jumped ', '7 times over ', '7 lazy dogs']
0
M. I. Wright 2 Фев 2019 в 20:50

Простой и наивный способ сделать это - просто найти индекс того, на что вы хотите разделить, и нарезать его:

>>> a = 'cats can jump up to 7 times their tail length'
>>> ind = a.index('7')
>>> a[:ind], a[ind:]
('cats can jump up to ', '7 times their tail length')
6
Rafael Barros 23 Фев 2018 в 15:10

Другой способ - использовать str.partition:

a = 'cats can jump up to 7 times their tail length'
print(a.partition('7'))
# ('cats can jump up to ', '7', ' times their tail length')

Чтобы снова объединить число с последней частью, вы можете использовать str.join:

x, *y = a.partition('7')
y = ''.join(y)
print((x, y))
# ('cats can jump up to ', '7 times their tail length')

Или сделайте это вручную:

sep = '7'
x = a.split(sep)
x[1] = sep + x[1]
print(tuple(x))
# ('cats can jump up to ', '7 times their tail length')
5
Graipher 23 Фев 2018 в 15:13