2016-01-29 184 views
4

我想替换字符串中第n个出现的子字符串。替换字符串中出现的第n个子字符串

一定有什么东西相当于什么我想要做的是

mystring.replace("substring", 2nd)

什么是实现这一目标的最简单,最Python的方式?

为什么不重复:我不想使用这种方法的正则表达式,我发现大多数类似问题的答案只是正则表达式的剥离或真正复杂的功能。我真的希望尽可能简单,而不是正则表达式解决方案。

+1

@Tiger哇。你如何找到确切的愚蠢?似乎我的答案也在那里.. :-) –

+0

回复:不重复:请读过去的第一个答案。 – TigerhawkT3

+0

@ TigerhawkT3啊,我明白了。他要求提供正则表达式解决方案,但他也得到了非正则表达式的答案。我没有读过它们。你能编辑他的问题吗? – aleskva

回答

0

我使用简单的函数,它列出所有的事件,选择第n个位置并使用它将原始字符串拆分为两个子字符串。然后,它取代了第二子第一次出现,并加入子回新的字符串:

import re 

def replacenth(string, sub, wanted, n) 
    where = [m.start() for m in re.finditer(sub, string)][n-1] 
    before = string[:where] 
    after = string[where:] 
    after = after.replace(sub, wanted, 1) 
    newString = before + after 
    print newString 

对于这些变量:

string = 'ababababababababab' 
sub = 'ab' 
wanted = 'CD' 
n = 5 

输出:

ababababCDabababab 

注:

The where变量实际上是一系列匹配的位置,你从哪里拿到第n个。但是列表项索引通常以0开头,而不是1。因此有一个n-1索引和n变量是实际的第n个子字符串。我的例子发现第五个字符串如果您使用n索引并想查找第5个位置,则需要n4。你使用的通常取决于功能,它产生我们的n

这应该是最简单的方法,但也许它不是最Pythonic方式,因为where变量构造需要导入re库。也许有人会发现更多的Pythonic方式。

来源,另外一些链接:

5

您可以使用while循环使用str.find找到第n个出现,如果它ex派并使用该位置来创建新的字符串:

def nth_repl(s, sub, repl, nth): 
    find = s.find(sub) 
    # if find is not p1 we have found at least one match for the substring 
    i = find != -1 
    # loop util we find the nth or we find no match 
    while find != -1 and i != nth: 
     # find + 1 means we start at the last match start index + 1 
     find = s.find(sub, find + 1) 
     i += 1 
    # if i is equal to nth we found nth matches so replace 
    if i == nth: 
     return s[:find]+repl+s[find + len(sub):] 
    return s 

例子:

In [14]: s = "foobarfoofoobarbar" 

In [15]: nth_repl(s, "bar","replaced",3) 
Out[15]: 'foobarfoofoobarreplaced' 

In [16]: nth_repl(s, "foo","replaced",3) 
Out[16]: 'foobarfooreplacedbarbar' 

In [17]: nth_repl(s, "foo","replaced",5) 
Out[17]: 'foobarfoofoobarbar' 
1

最后的答案几乎是完美的 - 只有一个修正:

def replacenth(string, sub, wanted, n): 
     where = [m.start() for m in re.finditer(sub, string)][n - 1] 
     before = string[:where] 
     after = string[where:] 
     after = after.replace(sub, wanted) 
     newString = before + after 
     return newString 

后串有在更换后再次存储在这个变量中。 谢谢你的伟大的解决方案!

1

我已经想出了下面的内容,它也考虑了将所有“旧”字符串事件替换为左侧或右侧的选项。自然,没有选择来替换所有的事件,因为标准的str.replace工作得很完美。

def nth_replace(string, old, new, n=1, option='only nth'): 
    """ 
    This function replaces occurrences of string 'old' with string 'new'. 
    There are three types of replacement of string 'old': 
    1) 'only nth' replaces only nth occurrence (default). 
    2) 'all left' replaces nth occurrence and all occurrences to the left. 
    3) 'all right' replaces nth occurrence and all occurrences to the right. 
    """ 
    if option == 'only nth': 
     left_join = old 
     right_join = old 
    elif option == 'all left': 
     left_join = new 
     right_join = old 
    elif option == 'all right': 
     left_join = old 
     right_join = new 
    else: 
     print("Invalid option. Please choose from: 'only nth' (default), 'all left' or 'all right'") 
     return None 
    groups = string.split(old) 
    nth_split = [left_join.join(groups[:n]), right_join.join(groups[n:])] 
    return new.join(nth_split) 
相关问题