views:

104

answers:

5

How to replace a set of characters inside another string in Python?

Here is what I'm trying to do: let's say I have a string 'abcdefghijkl' and want to replace the 2-d from the end symbol (k) with A. I'm getting an error:

>>> aa = 'abcdefghijkl'
>>> print aa[-2]
k
>>> aa[-2]='A'

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    aa[-2]='A'
TypeError: 'str' object does not support item assignment

So, the question: is there an elegant way to replace (substitute) with a string symbols inside another string starting from specified position? Something like:

# subst(whole_string,symbols_to_substiture_with,starting_position)

>>> print aa
abcdefghijkl
>>> aa = subst(aa,'A',-2)
>>> print aa
abcdefghijAl

What would be a not-brute-force code for the subst?

+4  A: 
TypeError: 'str' object does not support item assignment

This is to be expected - python strings are immutable.

One way is to do some slicing and dicing. Like this:

>>> aa = 'abcdefghijkl'
>>> changed  = aa[0:-2] + 'A' + aa[-1]
>>> print changed
abcdefghijAl

The result of the concatenation, changed will be another immutable string. Mind you, this is not a generic solution that fits all substitution scenarios.

Manoj Govindan
You're missing the trailing 'l' character.
gnucom
@gnucom: Thanks. Fixed it.
Manoj Govindan
+1. Thanks for that.
gnucom
+3  A: 

If it's always the same position you're replacing, you could do something like:

>>> s = s[0:-2] + "A" + s[-1:]
>>> print s
abcdefghijAl

In the general case, you could do:

>>> rindex = -2 #Second to the last letter
>>> s = s[0:rindex] + "A" + s[rindex+1:]
>>> print s
abcdefghijAl

Edit: The very general case, if you just want to repeat a single letter in the replacement:

>>> s = "abcdefghijkl"
>>> repl_str = "A"
>>> rindex = -4 #Start at 4th character from the end
>>> repl = 3 #Replace 3 characters
>>> s = s[0:rindex] + (repl_str * repl) + s[rindex+repl:]
>>> print s
abcdefghAAAl
eldarerathis
@eldarerathis: What if the substitution is longer than 1 symbol? 'AAA' instead of 'A'. And I need to replace three symbols in the original string (not one with three, but the same length as the substitution).
@photographer: See my edit.
eldarerathis
+2  A: 

You have to slice it up and instantiate a new string since strings are immutable:

aa = aa[:-2] + 'A' + aa[-1:]
Eric Mickelsen
+1  A: 

Another way to do this:

s = "abcdefghijkl"
l = list( s )
l[-2] = 'A'
s = "".join( l )

Strings in Python are immutable sequences - very much like tuples. You can make a list, which is mutable, from string or tuple, change relevant indexes and transform the list back into string with join or into tuple with tuple constructor.

EDIT: in case of strings you can use bytearray (docs) type instead of list, which makes transforming into string possible with str constructor.

Also, you could implement your own or use this class from standard library: http://docs.python.org/library/userdict.html#UserString.MutableString like so:

>>> from UserString import MutableString
>>> s = MutableString( "zdfgzbdr " )
>>> s
'zdfgzbdr '
>>> s[1:5]
'dfgz'
>>> s[1:5] = "xxxx"
>>> s
'zxxxxbdr '

Sadly - MutableString is deprecated and not available in Py3k (you can still write your own class, I think).

cji
Cheer up, you still have `bytearray`
gnibbler
@gnibbler I'm amazed. I didn't know this type exists, thanks.
cji
A: 

To reply comment of other post:

To make three character substitution directly with strings (see also the bytearray post) you can do partition with the sequence, especially if you do not know the position without search:

aa = 'abcdefghijkl'
replace = 'def'
withstring = 'QRS'
newstr,found,endpart = aa.partition(replace)

if found:
    newstr+=withstring+endpart
    print newstr
else:
    print "%r string is not in %r" % (replace,aa)

The length of replacement does not need to match the original in this case.

Tony Veijalainen