kostiak
kostiak

Reputation: 6501

Changing a character in a string

What is the easiest way in Python to replace a character in a string?

For example:

text = "abcdefg";
text[1] = "Z";
           ^

Upvotes: 571

Views: 1229616

Answers (17)

N1ngu
N1ngu

Reputation: 3805

A more general formula to replace slices instead of single character positions, convenient for working with fixed-width documents and protocols:

def replace(old:str, ss:slice, new:str):
    return old[:ss.start] + new + old[ss.stop:]

print(replace("abcdefg", slice(1,3), "xx"))

Upvotes: 0

Jochen Ritzel
Jochen Ritzel

Reputation: 107598

new = text[:1] + 'Z' + text[2:]

Upvotes: 160

Mehdi Nellen
Mehdi Nellen

Reputation: 8964

Fastest method?

There are three ways.
For the speed seekers I recommend 'Method 2'

Method 1:

Given by scvalex's answer:

text = 'abcdefg'
new = list(text)
new[6] = 'W'
''.join(new)

Which is pretty slow compared to 'Method 2':

timeit.timeit("text = 'abcdefg'; s = list(text); s[6] = 'W'; ''.join(s)", number=1000000)
1.0411581993103027

Method 2 (FAST METHOD):

Given by Jochen Ritzel's answer:

text = 'abcdefg'
text = text[:1] + 'Z' + text[2:]

Which is much faster:

timeit.timeit("text = 'abcdefg'; text = text[:1] + 'Z' + text[2:]", number=1000000)
0.34651994705200195

Method 3:

Byte array:

timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000)
1.0387420654296875

Upvotes: 329

passionatedevops
passionatedevops

Reputation: 539

try this :

old_string = "mba"
string_list = list(old_string)
string_list[2] = "e"
//Replace 3rd element

new_string = "".join(string_list)

print(new_string)

Upvotes: -1

eapetcho
eapetcho

Reputation: 527

A solution combining find and replace methods in a single line if statement could be:

my_var = "stackoverflaw"
my_new_var = my_var.replace('a', 'o', 1) if my_var.find('s') != -1 else my_var
print(f"my_var = {my_var}")           # my_var = stackoverflaw
print(f"my_new_var = {my_new_var}")   # my_new_var = stackoverflow

Upvotes: 0

cottontail
cottontail

Reputation: 23021

If you're changing only one character, then the answer from Jochen Ritzel that uses string slicing is the fastest (and most readable imo). However, if you're going to change multiple characters in a string by position that way doesn't scale well. In that case, there's a builtin array module that could be useful to convert the string mutable object and change the required characters. Obviously converting to a list (as done in the accepted answer) also works but it's very slow.

import array
text = "HXlYo wZrWd"
ix = [1, 3, 7, 9]
vs = ['e', 'l', 'o', 'l']

ar = array.array('u', text)     # convert `text` string to array.array object
for i,v in zip(ix, vs):
    ar[i] = v                   # change characters by index
out = ar.tounicode()            # convert back to string
print(out)  # Hello world

Upvotes: 1

scvalex
scvalex

Reputation: 15335

Don't modify strings.

Work with them as lists; turn them into strings only when needed.

>>> s = list("Hello zorld")
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'z', 'o', 'r', 'l', 'd']
>>> s[6] = 'W'
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
>>> "".join(s)
'Hello World'

Python strings are immutable (i.e. they can't be modified). There are a lot of reasons for this. Use lists until you have no choice, only then turn them into strings.

Upvotes: 761

K.Vee.Shanker.
K.Vee.Shanker.

Reputation: 305

This code is not mine. I couldn't recall the site form where, I took it. Interestingly, you can use this to replace one character or more with one or more charectors. Though this reply is very late, novices like me (anytime) might find it useful.

Change Text function.

mytext = 'Hello Zorld'
# change all Z(s) to "W"
while "Z" in mytext:
      # replace "Z" to "W"
      mytext = mytext.replace('Z', 'W')
print(mytext)

Upvotes: 9

Highbrow Director
Highbrow Director

Reputation: 87

To replace a character in a string

You can use either of the method:

Method 1

In general,

string = f'{string[:index]}{replacing_character}{string[index+1:]}'

Here

text = f'{text[:1]}Z{text[2:]}'

Method 2

In general,

string = string[:index] + replacing_character + string[index+1:]

Here,

text = text[:1] + 'Z' + text[2:]

Upvotes: 0

OsorioSP
OsorioSP

Reputation: 81

I like f-strings:

text = f'{text[:1]}Z{text[2:]}'

In my machine this method is 10% faster than the "fast method" of using + to concatenate strings:

>>> timeit.timeit("text = 'abcdefg'; text = text[:1] + 'Z' + text[2:]", number=1000000)
1.1691178000000093
>>> timeit.timeit("text = 'abcdefg'; text = f'{text[:1]}Z{text[2:]}'", number =1000000)
0.9047831999999971
>>>

Upvotes: 7

Manoj Kumar S
Manoj Kumar S

Reputation: 740

Strings are immutable in Python, which means you cannot change the existing string. But if you want to change any character in it, you could create a new string out it as follows,

def replace(s, position, character):
    return s[:position] + character + s[position+1:]

replace('King', 1, 'o')
// result: Kong

Note: If you give the position value greater than the length of the string, it will append the character at the end.

replace('Dog', 10, 's')
// result: Dogs

Upvotes: 11

Martin Beckett
Martin Beckett

Reputation: 96119

Python strings are immutable, you change them by making a copy.
The easiest way to do what you want is probably:

text = "Z" + text[1:]

The text[1:] returns the string in text from position 1 to the end, positions count from 0 so '1' is the second character.

edit: You can use the same string slicing technique for any part of the string

text = text[:1] + "Z" + text[2:]

Or if the letter only appears once you can use the search and replace technique suggested below

Upvotes: 61

mohammed wazeem
mohammed wazeem

Reputation: 1328

I would like to add another way of changing a character in a string.

>>> text = '~~~~~~~~~~~'
>>> text = text[:1] + (text[1:].replace(text[0], '+', 1))
'~+~~~~~~~~~'

How faster it is when compared to turning the string into list and replacing the ith value then joining again?.

List approach

>>> timeit.timeit("text = '~~~~~~~~~~~'; s = list(text); s[1] = '+'; ''.join(s)", number=1000000)
0.8268570480013295

My solution

>>> timeit.timeit("text = '~~~~~~~~~~~'; text=text[:1] + (text[1:].replace(text[0], '+', 1))", number=1000000)
0.588400217000526

Upvotes: -1

Paul Nathan
Paul Nathan

Reputation: 40299

if your world is 100% ascii/utf-8(a lot of use cases fit in that box):

b = bytearray(s, 'utf-8')
# process - e.g., lowercasing: 
#    b[0] = b[i+1] - 32
s = str(b, 'utf-8')

python 3.7.3

Upvotes: 0

Mahmoud
Mahmoud

Reputation: 539

Starting with python 2.6 and python 3 you can use bytearrays which are mutable (can be changed element-wise unlike strings):

s = "abcdefg"
b_s = bytearray(s)
b_s[1] = "Z"
s = str(b_s)
print s
aZcdefg

edit: Changed str to s

edit2: As Two-Bit Alchemist mentioned in the comments, this code does not work with unicode.

Upvotes: 14

user5587487
user5587487

Reputation: 39

Actually, with strings, you can do something like this:

oldStr = 'Hello World!'    
newStr = ''

for i in oldStr:  
    if 'a' < i < 'z':    
        newStr += chr(ord(i)-32)     
    else:      
        newStr += i
print(newStr)

'HELLO WORLD!'

Basically, I'm "adding"+"strings" together into a new string :).

Upvotes: 3

Unknown
Unknown

Reputation: 46773

Like other people have said, generally Python strings are supposed to be immutable.

However, if you are using CPython, the implementation at python.org, it is possible to use ctypes to modify the string structure in memory.

Here is an example where I use the technique to clear a string.

Mark data as sensitive in python

I mention this for the sake of completeness, and this should be your last resort as it is hackish.

Upvotes: 9

Related Questions