Arkistarvh Kltzuonstev
Arkistarvh Kltzuonstev

Reputation: 6935

Python : replace multiple occurrence of characater by one but single occurrence by none

I have a string:

a = '0202201131181'

I want to replace all multiple occurrences of 1 in a if present, by a single 1 but if only one occurrence of '1' is found then replace it by empty string ''.

My end goal is to get:

a = '0202201318'

Here the '1' after character '8' is occurring only once, so it's replaced by empty string, but the '11' before the character '3' and after the character, '3' is replaced by '1'.

Here is an if-else code block I tried, which is partially correct:

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

But it outputs '02022013181', which is incorrect. How to do this?

Upvotes: 4

Views: 2570

Answers (5)

Ora Aff
Ora Aff

Reputation: 682

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)

I tried the following few cases with the above code:

a = '111020220113111111'          >> 1020220131
a = '020220111311811001001001001' >> 02022013181001001001001
a = '0202201131181'               >> 02022013181

NOTE: Edited my earlier code.

Upvotes: 0

virolino
virolino

Reputation: 2227

Non-regex solution, inspired by @Jay. I have zero knowledge of Python, so syntax probably needs alteration. Of course, not tested. "Benefit": conditions are less complicated (I hope).

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))

Upvotes: 0

Jay
Jay

Reputation: 24905

Regex based solution is the best. No two thoughts on that.

Just a another logic without using regular expressions, just for the record:

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))

Output:

02022013181

Upvotes: 1

iz_
iz_

Reputation: 16623

Regex is probably the best option:

import re

a = '020220111311811001001001001'

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

First sub out single 1s, then sub out multiple occurrences of 1. I added some more characters to a for testing purposes, and the output is

0202201318100000000

If you don't like the somewhat confusion caused by the one-liner:

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

Explanation of (?<!1)1(?=[^1]|$):

  • (?<!1): Make sure the character before is not a 1.
  • 1: Literally match a 1.
  • (?=[^1]|$): Make sure the character ahead is either a) not a 1, or b) is the end of the string.

Upvotes: 11

Shivam Pandya
Shivam Pandya

Reputation: 261

This is a way to achieve the expected output without using regex. What I am doing is, I am splitting the string from '11' and the replacing all the '1's with empty space and joining the list into string with '1' again.

a = '0202201131181'
tmp =[ i.replace('1', '') for i in a.split('11')]
print(('1').join(tmp))

Breakdown of the list comprehension:

a = '0202201131181'
tmp =[]

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

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

Upvotes: 0

Related Questions