Skip to main content
 首页 » 编程设计

Python:替换字符串,从列表中匹配

2025年05月04日38tuyile006

尝试匹配和标记基于字符的 n-gram。字符串

txt = "how does this work" 

要与列表中的 n-gram 匹配

ngrams = ["ow ", "his", "s w"] 

并标有<> – 但是,前提是没有前面的开价。我正在寻找此字符串的输出是 h<ow >does t<his w>ork (注意 2-nd 部分中的双重匹配,但仅在一对预期引号内)。

然而,我为此尝试过的 for 循环根本没有产生想要的输出:

switch = False 
 
for i in txt: 
    if i in "".join(ngrams) and switch == False: 
        txt = txt.replace(i, "<" + i) 
        switch = True 
    if i not in "".join(ngrams) and switch == True: 
        txt = txt.replace(i, ">" + i) 
        switch = False 
 
print(txt) 

如有任何帮助,我们将不胜感激。

请您参考如下方法:

此解决方案使用 str.find 方法在 txt 字符串中查找 ngram 的所有副本,将每个副本的索引保存到 indices 设置以便我们可以轻松处理重叠匹配。

然后我们复制 txt,一个字符一个字符地复制到 result 列表,在需要的地方插入尖括号。此策略比使用多个 .replace 调用插入尖括号更有效,因为每个 .replace 调用都需要重建整个字符串。

我稍微扩展了您的数据以说明我的代码处理 ngram 的多个副本。

txt = "how does this work now chisolm" 
ngrams = ["ow ", "his", "s w"] 
print(txt) 
print(ngrams) 
 
# Search for all copies of each ngram in txt 
# saving the indices where the ngrams occur 
indices = set() 
for s in ngrams: 
    slen = len(s) 
    lo = 0 
    while True: 
        i = txt.find(s, lo) 
        if i == -1: 
            break 
        lo = i + slen  
        print(s, i) 
        indices.update(range(i, lo-1)) 
 
print(indices) 
 
# Copy the txt to result, inserting angle brackets 
# to show matches 
switch = True 
result = [] 
for i, u in enumerate(txt): 
    if switch: 
        if i in indices: 
            result.append('<') 
            switch = False 
        result.append(u) 
    else: 
        result.append(u) 
        if i not in indices: 
            result.append('>') 
            switch = True 
 
print(''.join(result)) 

输出

how does this work now chisolm 
['ow ', 'his', 's w'] 
ow  1 
ow  20 
his 10 
his 24 
s w 12 
{1, 2, 10, 11, 12, 13, 20, 21, 24, 25} 
h<ow >does t<his w>ork n<ow >c<his>olm 

如果你想合并相邻的组,我们可以使用 str.replace 方法轻松地做到这一点。但要使其正常工作,我们需要预处理原始数据,将所有空格转换为单个空格。一种简单的方法是拆分数据并重新加入。

txt = "how  does this\nwork  now chisolm hisow" 
ngrams = ["ow", "his", "work"] 
 
#Convert all whitespace to single spaces 
txt = ' '.join(txt.split()) 
 
print(txt) 
print(ngrams) 
 
# Search for all copies of each ngram in txt 
# saving the indices where the ngrams occur 
indices = set() 
for s in ngrams: 
    slen = len(s) 
    lo = 0 
    while True: 
        i = txt.find(s, lo) 
        if i == -1: 
            break 
        lo = i + slen  
        print(s, i) 
        indices.update(range(i, lo-1)) 
 
print(indices) 
 
# Copy the txt to result, inserting angle brackets 
# to show matches 
switch = True 
result = [] 
for i, u in enumerate(txt): 
    if switch: 
        if i in indices: 
            result.append('<') 
            switch = False 
        result.append(u) 
    else: 
        result.append(u) 
        if i not in indices: 
            result.append('>') 
            switch = True 
 
# Convert the list to a single string 
output = ''.join(result) 
 
# Merge adjacent groups 
output = output.replace('> <', ' ').replace('><', '') 
print(output) 

输出

how does this work now chisolm hisow 
['ow', 'his', 'work'] 
ow 1 
ow 20 
ow 34 
his 10 
his 24 
his 31 
work 14 
{32, 1, 34, 10, 11, 14, 15, 16, 20, 24, 25, 31} 
h<ow> does t<his work> n<ow> c<his>olm <hisow>