0

I was creating a function about replacing multiple part of a string with multiple number but for some reason, the output is not what i expected.

from pyprimes import isprime
def prime_replace(x, l = []):
    lst = []
    string = str(x)
    for n in range(10):
        for i in l:
            string = string.replace(string[i], str(n))
        lst.append(int(string))
    return lst 

print prime_replace(x = 56243, l = [2, 3])

The output of this function is a list [56003, 56113, 56223, 56333, 56444, 56555, 66666, 77777, 88888, 99999] but what i wanted is [56003, 56113, 56223, 56333, 56443, 56553, 56663, 56773, 56883, 56993] Can someone help me with this and tell me what went wrong, thank you.

V.Anh
  • 497
  • 3
  • 8
  • 15

4 Answers4

3

You're modifying the original string, and replace is replacing "all occurrences"

Here's part of a print out for how it's generating the output you see:

...
string is now 56333
replacing 3 with 3
string is now 56333
replacing 3 with 4
string is now 56444
...

You can see that we successfully got 56333 like you wanted, but then you wanted to replace str[2] (actual value: 3) with str(n) (actual value: 4), which replaced all occurrences of 3

One workaround for this specific scenario is to make a copy of your string:

def prime_replace(x, l = []):
    lst = []
    string = str(x)
    for n in range(10):
        newstr = string
        for i in l:
            newstr = newstr.replace(string[i], str(n))
        lst.append(int(newstr))
    return lst 

print prime_replace(x = 56243, l = [2, 3])

Output:

[56003, 56113, 56223, 56333, 56443, 56553, 56663, 56773, 56883, 56993]

Demo (not recommended)

However, replace may not be the best choice since it will replace all occurrences of the "oldstring" with the "newstring". It looks like what you're really trying to do is to change string at indices in l to be the next value in range(10), we can do this through indexing and appending:

def prime_replace(x, l = []):
    lst = []
    string = str(x)
    for n in range(10):
        newstr = string
        for i in l:
            newstr = newstr[0:i]+str(n)+newstr[i+1:];
        lst.append(int(newstr))
    return lst 

Demo (better)

AndyG
  • 39,700
  • 8
  • 109
  • 143
0

string.replace(a,b) replaces all instances of a with b. so, '56243'.replace(3,0) evaluates to '56240'. You are trying to replace the values at the indicies in l, so you should replace

string = string.replace(string[i], str(n))

with

string = string[:i] + str(n) + string[i+1:]

The other answer fails on cases where the value at an index to be replaced is repeated elsewhere in the number, i.e. prime_replace(562432,[2,3])

E.D.
  • 639
  • 6
  • 14
0

I have also found another solution for it by turning the string into list

from pyprimes import isprime
def prime_replace(x, l):
    lst = []
    string_lst = list(str(x))
    for n in range(10):
        for i in l:
            string_lst[i] = str(n)
        lst.append(int("".join(string_lst)))
    return lst 

print prime_replace(56243, [2, 3])

Output

[56003, 56113, 56223, 56333, 56443, 56553, 56663, 56773, 56883, 56993]

But thank you very much for your solution.

V.Anh
  • 497
  • 3
  • 8
  • 15
0

You really want a mutable data-structure here to simplify your logic. You can get what is essentially a mutable string by using a bytearray. So here is an alternative approach:

In [11]: def prime_replace(x, l=None):
    ...:     if l is None:
    ...:         l = [] # careful with mutable default arguments
    ...:     lst = []
    ...:     string = bytearray(str(x), encoding='ascii')
    ...:     for n in b'0123456789':
    ...:         for i in l:
    ...:             string[i] = n
    ...:         lst.append(int(string))
    ...:     return lst
    ...:

In [12]: prime_replace(x = 56243, l = [2, 3])
Out[12]: [56003, 56113, 56223, 56333, 56443, 56553, 56663, 56773, 56883, 56993]

Also, be careful with mutable default arguments.

I use a bytearray because I think it simplifies things more. A list also works. But note with bytearray and by iterating directly over the ascii b'012345679' it simplifies everything by a lot, and you don't have to keep converting things back-and-forth between str and int

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172