使用 itertools 出现第 n 个子字符串

问题描述 投票:0回答:5

我正在尝试编写一个函数,该函数返回一个字符串,其中第 n 个子字符串被新的子字符串替换。

我尝试了以下方法:

import re
from itertools import count

text = "Hello_Dear_Today_is_Nice_Today_is_Nice"

def replace_nth(text, sub, rep_sub, n):
    c = count(0)
    res = re.sub(r"{}".format(sub), lambda x: rep_sub if next(c) == n else x.group(), text)
    return res

print(replace_nth(text, "Today", "Today_2", 2))

但是返回的字符串是一样的,我做错了什么?

我期待:

结果

Hello_Dear_Today_is_Nice_Today_2_is_Nice

python regex string python-itertools python-re
5个回答
0
投票

尝试:

import re
from itertools import islice


def replace_nth(text, sub, rep_sub, n):
    r = re.finditer(re.escape(sub), text)

    for m in islice(r, n - 1, n):
        text = f"{text[:m.start()]}{rep_sub}{text[m.end():]}"
        break

    return text


text = "Hello_Dear_Today_is_Nice_Today_is_Nice"
print(replace_nth(text, "Today", "Today_2", 2))

打印:

Hello_Dear_Today_is_Nice_Today_2_is_Nice

0
投票

我猜你想从后面更换它。

如果是这样的话,您可以简单地使用

split()


text = "Hello_Dear_Today_is_Nice_Today_is_Nice"


def replace_nth(text, sub, rep_sub, n):
    s = text.split('_')
    s[-n - 1] = rep_sub
    return '_'.join(s)


print(replace_nth(text, "Today", "Today_2", 2))



Hello_Dear_Today_is_Nice_Today_2_is_Nice

编辑:

您似乎正在尝试从左侧进行匹配。在这种情况下:

def replace_nth(text, sub, rep_sub, n):
    s = text.split('_')
    for i, word in enumerate(s):
        if word.startswith(sub):
            n -= 1
            if n == 0:
                s[i] = rep_sub
                break
    return '_'.join(s) if n == 0 else 'False inputs'


text = "Hello_Dear_Today_is_Nice_Today_is_Nice"
print(replace_nth(text, "Today", "Today_2", 2))
print(replace_nth(text, "Today", "Today_2", 4))
print(replace_nth(text, "Today", "Today_2", 1))


Hello_Dear_Today_is_Nice_Today_2_is_Nice
False inputs
Hello_Dear_Today_2_is_Nice_Today_is_Nice

0
投票

一种方法是使用 re.finditer():

from re import finditer

text = "Hello_Dear_Today_is_Nice_Today_is_Nice"

def replace_nth(text, sub, rep_sub, n):
  m = list(finditer(sub, text))
  try:
    return f"{text[0:m[n].span()[0]]}{rep_sub}{text[m[n].span()[1]:]}"
  except IndexError:
    return text

x = replace_nth(text, "Today", "Today_2", 1)

print(x)

通过异常处理完成的小错误处理将确保如果未找到第

n
匹配项或
text
不包含
sub
,则返回原始文本。


0
投票

没有任何依赖,肯定比 re/itertools 快很多。 如果字符串包含子字符串 n 次,则分割后的数字必须为 n+1 。如果情况并非如此,该函数将返回 None

def replace_nth(text, sub, rep_sub, n):
    return (sub.join(g[:n]) + rep_sub + g[n]) if len(g:=text.split(sub,maxsplit=n))==n+1 else None

text = "Hello_Dear_Today_is_Nice_Today_is_Nice"

print(replace_nth(text, "Today", "Today_2", 2))

0
投票

您可以在匹配第 n 次出现的

n - 1
之前构建一个匹配
sub
出现的
sub
的正则表达式:

def replace_nth(text, sub, rep_sub, n):
    if n > 1:
        sub = rf'^(.*?(?:{sub}.*?){{{n - 1}}}){sub}'
        rep_sub = r'\1' + rep_sub
    return re.sub(sub, rep_sub, text, count=1)

演示:https://ideone.com/XsqgGE

© www.soinside.com 2019 - 2024. All rights reserved.