1

I am trying to replace a specific character at a specific position in a string.

This need to be accomplished without for loop and use of functions.

Here is an example - need to replace 5th character with x s = "0123456789012345689" Output needs to be - "01234x67890x23456x89" I have tried replace(), split() but may be I am not using them in correct context. The string could be n characters long so I can't hardcode where I get the specific position and break them down in substrings. String are supposed to be immutable in python so are there any other alternatives?

Any help would be appreciated. Thanks.

2
  • 1
    Why such an arbitrary list of conditions? Is this homework? Technically, basically everything in Python is a function (somewhat), and for loops are loops too. Commented Feb 2, 2020 at 23:03
  • 1
    Maybe you want to show your code so we can tell what you did wrong? Commented Feb 2, 2020 at 23:06

3 Answers 3

1

I guess, if you strictly want to avoid for loops, the easiest way is converting to a list, replacing items, and then converting back.

This would be:

s = "0123456789012345689"
lst = list(s)   # result: ['0', '1', '2', ..., '9']
lst[0:-1:5] = ["x"]*len(lst[0:-1:5])

Result then is:

In [43]: lst                                                                                                                                                                                                         
Out[43]: 
['x',
 '1',
 '2',
 '3',
 '4',
 'x',
 '6',
 '7',
 '8',
 '9',
 'x',
 '1',
 '2',
 '3',
 '4',
 'x',
 '6',
 '8',
 '9']

For getting it back to string you would simply use a join:

In [44]: "".join(lst)                                                                                                                                                                                                
Out[44]: 'x1234x6789x1234x689

The part lst[0:-1:5] select every 5th element in the list, beginning with the very first entry, denonted by 0:. If you want it to start at the 5th element, then simply do lst[5:-1:5]. The -1 part means "until the end", the last :5 stands for "every fifth".

Assigning values with ["x"]*len(lst[0:-1:5]) is needed, since "x" here would try to assign a single value to a slice of the original list with the length len(lst[0:-1:5]), because this is exactly how many items we selected in the first place.


EDIT: Giving it a second look the expected outcome is actually to change every 6th character, not every 5th (while preserving 5 characters in between the changed ones from the original string).

One would then, of course, need to adjust the slicing to select every 6th character:

lst[5:-1:6] = ["x"]*len(lst[5:-1:6])
         ^                       ^

Result:

In [12]: "".join(lst)                                                                                                                                                                                                
Out[12]: '01234x67890x23456x9'

Every sixth character now is being replaced, while preserving the 5 ones in between from the original string.

Sign up to request clarification or add additional context in comments.

6 Comments

This doesn't quite match the OP's expected output. Every fifth character should be set to x, not every character whose index is a multiple of 5.
@Brian this is exactly the same, you just need to change the indexing to lst[5:-1:5], as mentioned in the post. I made the example starting with the very first entry (i.e. lst[0:-1:5]) for explanation reasons only: taking lst[5:-1:5] as an example, which would give the desired output, leaves a beginner without a clue which 5 is responsible for which action.
I suggest you compare the output of this technique with that update, 01234x6789x1234x689, with the OP's expected value, 01234x67890x23456x89. You want to access every sixth element, leaving five characters between each separator.
@Brian ah yeah, I was misled by every fifth character. The result actually preserves 5 characters and then changes the 6th. Anyways, the solution is still valid. This would just change the indexing to lst[5:-1:6], nothing more.
@daniel451 this is great. This is what I was looking for. Thanks a lot.
|
1

My solution to this would be this:

def replace_position(message, replacement, n):
    lis = list(message)  # get a list of all characters.
    lis.pop(n)  # delete the chosen character from the list.
    lis.insert(n, replacement)  # replace it at the given position.

    return ''.join(lis)

Example use:

>>> a = 'Hello world, the 6th character is an x!'
>>> replace_postion(a, 'x', 6)
'Hello xorld, the 6th character is an x!'

However, this only gets the first one in that position. In order to do that, this is what I would do:

def replace_position(message, replacement, n):
    lis = list(message)
    for i in range(n, len(message), n + 1):
        lis.pop(i)
        lis.insert(i, replacement)

    return ''.join(lis) 

The only difference is that we are now iterating over the entire message, and replacing each of them as we go. Similar use:

>>> a = 'Hello world, every 6th character is an x!'
>>> replace_position(a, 'x', 6)
'Hello xorld, xvery 6xh charxcter ix an x!'

Hope this helps.

Comments

0

Try

s = "01234567890123456789012345"

pieces = []
for i in range((len(s)-1)//5):
    pieces.append(s[i*6:i*6+5])

result = 'x'.join(pieces)

assert(result ==  '01234x67890x23456x89012x45')

We iterator over every window of six characters in the string, and then collect the first five characters in each window. We then join all of the windows together, using the string x as a separator.

To avoid using loops, you can convert the above into a list comprehension. I'll leave this step for you to complete.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.