2010-08-11 14 views
16

En Python, las cadenas son inmutables.modificaciones de cadenas "in situ" en Python

¿Cuál es el modismo estándar para recorrer una cadena carácter por carácter y modificarla?

Los únicos métodos en los que puedo pensar son algunos hacks genuinamente stanky relacionados con unirse contra una cadena de resultados.

-

En C:

for(int i = 0; i < strlen(s); i++) 
{ 
    s[i] = F(s[i]); 
} 

Ésta es súper expresivo y dice exactamente lo que estoy haciendo. Eso es lo que estoy buscando.

+0

supongo, ya que son inmutables no se puede "modificarlo "... ¿Te refieres a construir una nueva cadena char-by-char? –

+0

Esto es realmente raro. ¿Puedes dar un contexto o un caso de uso para hacer esto? –

+0

Agregar ruido a un mensaje para probar. –

Respuesta

1

Las cadenas son iterables y se pueden recorrer a través de listas similares. Las cadenas también tienen una serie de métodos básicos como .replace() que podría ser lo que estás buscando. Todos los métodos de cadena devuelven una nueva cadena. Entonces, en lugar de modificar la cadena en su lugar, simplemente puede reemplazar su valor existente.

>>> mystring = 'robot drama' 
>>> mystring = mystring.replace('r', 'g') 
>>> mystring 
'gobot dgama' 
+0

Las cadenas son * inmutables * y el miembro no puede asignarlas. –

+0

Correcto. Todas las operaciones de cadena devuelven una copia de la cadena de entrada. Sin embargo, el nombre de la variable NO es inmutable, por lo que reasignando una operación de cadena al mismo nombre de variable, está efectivamente "mutando" la cadena. – jathanism

+0

"En el caso del medidor de alteraciones a un sting, que no inchalen y decgese su longitud, aún sería útil si se pudiera usar la notación de división de los ajustes in situ de niebla:' myStr [0: 3] [:] = 'new'' ".replace (" g "," r ") – CoDEmanX

1
>>> mystring = "Th1s 1s my str1ng" 
>>> mystring.replace("1", "i") 
'This is my string' 

Si desea almacenar la actual secuencia nueva que tendrá que mystring = mystring.replace("1", "i"). Esto es porque en Python las cadenas son inmutables.

+0

1: No utilice" cadena "como nombre de variable. 2: Eso no modifica la variable. – bstpierre

+0

Eso no selecciona por índice y lo modifica. –

+0

@bstpierre: ahí tienes. :) –

1

string.translate es probablemente la función más cercana a lo que está buscando.

+0

función interesante - lo que estoy buscando, sin embargo, es ser capaz de ajustar a un índice dado (o devolver una cadena que tiene ese índice dado modificado). –

+0

no es necesario importar desde la cadena, los objetos 'str' tienen el método' translate'. Por lo general, es útil usar 'maketrans' del módulo' 'string'' aunque –

15

No utilice una cadena, usar algo mutable como bytearray:

#!/usr/bin/python 

s = bytearray("my dog has fleas") 
for n in xrange(len(s)): 
    s[n] = chr(s[n]).upper() 
print s 

Resultados en:

MY DOG HAS FLEAS 

Editar:

Dado que este es un bytearray, no está (necesariamente) trabajando con caracteres. Está trabajando con bytes. Así que esto también funciona:

s = bytearray("\x81\x82\x83") 
for n in xrange(len(s)): 
    s[n] = s[n] + 1 
print repr(s) 

da:

bytearray(b'\x82\x83\x84') 

Si desea modificar caracteres de una cadena Unicode, tal vez querría trabajar con memoryview, sin embargo, que no es compatible con Unicode directamente .

+2

No son caracteres, sin embargo, solo bytes. Funciona solo para ASCII, no para Unicode. –

+2

Funciona para * bytes * válidos, no solo ASCII. – bstpierre

0
def modifyIdx(s, idx, newchar): 
    return s[:idx] + newchar + s[idx+1:] 
2

Asignación de un carácter particular a un índice determinado en una cadena no es una operación muy común, por lo que si ves que necesitas para hacerlo, piense si puede haber una mejor manera de realizar la tarea. Pero si lo necesita, probablemente la forma más estándar sería convertir la cadena en una lista, hacer sus modificaciones y luego convertirla a una cadena.

s = 'abcdefgh' 
l = list(s) 
l[3] = 'r' 
s2 = ''.join(l) 

EDIT: Tal como fue anunciado en la respuesta de bstpierre, bytearray es probablemente aún mejor para esta tarea que list, siempre y cuando usted no está trabajando con cadenas Unicode.

s = 'abcdefgh' 
b = bytearray(s) 
b[3] = 'r' 
s2 = str(b) 
+1

Y si está trabajando con cadenas multibyte, ¡tenga cuidado de no cortar un carácter codificado! –

0

Si alguna vez tengo que hacer algo como que acabo de convertir a una lista mutable

Por ejemplo ... (aunque sería más fácil de usar especie (véase el segundo ejemplo))

>>> s = "abcdfe" 
>>> s = list(s) 
>>> s[4] = "e" 
>>> s[5] = "f" 
>>> s = ''.join(s) 
>>> print s 
abcdef 
>>> 
# second example 
>>> s.sort() 
>>> s = ''.join(s) 
9

puede utilizar el módulo de UserString:

>>> import UserString 
... s = UserString.MutableString('Python') 
... print s 
Python 
>>> s[0] = 'c' 
>>> print s 
cython 
+5

Tenga en cuenta que MutableString quedó en desuso en Python 2.6 y se eliminó en Python 3 - https://docs.python.org/2/library/userdict.html#UserString.MutableString – msanders

1

Aquí hay un ejemplo usando traducir a cambiar "-" con "" y "A" mayúscula s

>>> from string import maketrans 
>>> trans_table = maketrans(".-a","-.A") 
>>> "foo-bar.".translate(trans_table) 
'foo.bAr-' 

Esto es mucho más eficiente que mover de un tirón a la matriz de bytes y de regreso si lo que tiene que hacer reemplazos de char individuales

15

El pitón analógica de su C:

for(int i = 0; i < strlen(s); i++) 
{ 
    s[i] = F(s[i]); 
} 

sería:

s = "".join(F(c) for c in s) 

que también es muy expresiva. Dice exactamente lo que está sucediendo, pero en un estilo funcional en lugar de un estilo de procedimiento.

+0

Interesante; Me gusta, excepto por la cadena nula. Probablemente tan bueno como me estoy poniendo. –

+1

Una parte importante de la C para mí es que funciona en el lugar. –

+1

@Joe Koberg: una parte importante de Python es que es más corto y más claro. "in situ" es limitante porque no puedes alargar la cadena. –

7

yo diría que la forma más Pythonic es utilizar map():

s = map(func, s) # func has been applied to every character in s 

Esto es el equivalente de la escritura:

s = "".join(func(c) for c in s) 
+3

Corrección/punto menor: Todavía se necesita volver a unir la lista devuelta (/ iter/map-obj en Py3 +). Así que lo anterior debe ser: 's = "" .join (mapa (func, s))' – pythonlarry

Cuestiones relacionadas