Python:将多个字符替换为一个,但将单个字符替换为空

4

I have a string:

a = '0202201131181'

如果存在多个 1,我希望将 a 中所有的多个 1 替换为单个 1,但是如果只有一个 '1',则将其替换为空字符串 ''。

我的最终目标是获得:

a = '0202201318'

这里字符“8”后面的“1”只出现一次,因此被替换为空字符串,但是字符“3”前面和后面的“11”被替换为“1”。

这是我尝试过的if-else代码块,部分正确:

if '11' in a:
    a = a.replace("11","1")
else:
    a = a.replace("1","")

但它输出了不正确的'02022013181'。怎么办?

1
你能连续拥有两个以上的1吗? - Taohidul Islam
@TaohidulIslam 是的,另一个示例可能是 a = '020220111311811',这种情况下,期望的输出将是 a = '02022013181' - Arkistarvh Kltzuonstev
5个回答

11

正则表达式可能是最好的选择:

import re

a = '020220111311811001001001001'

a = re.sub(r'1{2,}', '1', re.sub(r'(?<!1)1(?=[^1]|$)', '', a))
print(a)

首先替换单独的1,然后替换多个1。 我为了测试目的添加了一些字符到a中,并且输出是:

0202201318100000000

如果您不喜欢单行代码引起的混乱:

a = re.sub(r'(?<!1)1(?=[^1]|$)', '', a)
a = re.sub(r'1{2,}', '1', a)

(?<!1)1(?=[^1]|$)的解释:

  • (?<!1):确保当前字符前面不是1
  • 1:匹配单个字符1
  • (?=[^1]|$):确保当前字符后面是a) 非1字符,或者b) 字符串结尾。

点赞。我认为第二个正则表达式应该是1{1,1} - 更简单,更快。此外,我会将这两个替换操作实现为2个连续的语句 - 更容易看出正在发生什么。 - virolino
a = re.sub(r'([^1])1([^1])', '\1\2', a) 这段代码能正常工作吗?在我看来,应该是可以的... - virolino
@virolino 字符串的开头/结尾怎么样?同时,试试用 01010 - iz_
有点棘手 - 我的自尊心不得不承认失败 - 至少暂时是这样 :) - virolino
1
@PIG (?<!1): 确保前面的字符不是11: 字符串中匹配一个1(?=[^1]|$): 确保后面的字符要么a) 不是1,或者b) 是字符串的结尾。 - iz_
显示剩余8条评论

1

基于正则表达式的解决方案是最好的。毫无疑问。

只是为了记录,这里提供另一种不使用正则表达式的逻辑:

a = '110202201111311811'
new_str = []

for i in range(len(a)):
   if a[i] == '1':
       if (i!= (len(a)-1) and a[i+1] == '1') and (i!=0 and a[i-1] != '1'):
           new_str.append(a[i])
   else:
       new_str.append(a[i])

print ("".join(x for x in new_str))

输出:

02022013181

几乎就像是正则表达式的冒泡排序 :) 但如果不能使用正则表达式,我们必须处理它,没错。 - virolino
@virolino,没错。拥有另一个选项也无妨。 :) - Jay

0
这是一种不使用正则表达式实现期望输出的方法。 我的做法是,我从'11'处分割字符串,然后用空格替换所有的'1',再用'1'将列表连接成字符串。
a = '0202201131181'
tmp =[ i.replace('1', '') for i in a.split('11')]
print(('1').join(tmp))

列表推导式的分解:

a = '0202201131181'
tmp =[]

for i in a.split('11'):
  i = i.replace('1','')
  tmp.append(i)

print(('1').join(tmp))

当有超过两个连续的1时,它将无法工作。a = '0202201131181111' - PIG
@PIG 如果操作者想要进行递归操作,那么它将用“11”替换最后2对数字,并需要进行一次修订才能得到最终结果。否则根据当前条件,我认为它是正确的,因为它给出了“020220131811”作为最终结果。 - Shivam Pandya

0

无需正则表达式的解决方案,受 @Jay 启发而来。我对 Python 没有任何了解,所以语法可能需要更改。当然,没有经过测试。 "好处":条件不那么复杂(我希望如此)。

a = '110202201111311811'
new_str = []

while (not end of string) :
    while ((a[i]!='1') and (not end of string))
        new_str.append(a[i])
        i++

    if (a[i+1] is not out of range ) and (a[i+1] != '1') :
        i++
    else :
        new_str.append(a[i])
        while a[i]=='1' :
            i++

print ("".join(x for x in new_str))

0
a = '111020220113111111'
while a.find('11') != -1:
  i = 0
  j = 1
  while i < len(a):
    for c in a:
        if a[i] == '1':
            if a[j] == '1':
                a = a.replace(a[i],'x')
    i = i + 1
    j = i + 1
  a = a.replace("xx","1")
  a = a.replace("x","1")
print(a)

我使用上述代码尝试了以下几种情况:
a = '111020220113111111'          >> 1020220131
a = '020220111311811001001001001' >> 02022013181001001001001
a = '0202201131181'               >> 02022013181

注意:我已经编辑了之前的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接