length python string

length - python string substring



Invertir una cadena en Python (23)

No hay reverse función reverse incorporada para el objeto str de Python. ¿Cuál es la mejor manera de implementar este método?

Si proporciona una respuesta muy concisa, por favor explique su eficiencia. Por ejemplo, si el objeto str se convierte en un objeto diferente, etc.


¿Cuál es la mejor manera de implementar una función inversa para cadenas?

Mi propia experiencia con esta pregunta es académica. Sin embargo, si eres un profesional en busca de la respuesta rápida, usa una porción que paso por -1 :

>>> ''a string''[::-1] ''gnirts a''

o más legible (pero más lento debido a las búsquedas de nombres de métodos y al hecho de que unirse forma una lista cuando se le asigna un iterador), str.join :

>>> ''''.join(reversed(''a string'')) ''gnirts a''

o para facilitar la lectura y la reutilización, ponga la división en una función

def reversed_string(a_string): return a_string[::-1]

y entonces:

>>> reversed_string(''a_string'') ''gnirts_a''

Explicacion mas larga

Si estás interesado en la exposición académica, sigue leyendo.

No hay una función inversa incorporada en el objeto str de Python.

Aquí hay un par de cosas sobre las cuerdas de Python que debes saber:

  1. En Python, las cuerdas son inmutables . Cambiar una cadena no modifica la cadena. Crea uno nuevo.

  2. Las cuerdas son rebanables. Cortar una cadena te da una nueva cadena desde un punto de la cadena, hacia atrás o hacia adelante, a otro punto, en incrementos dados. Toman notación de división o un objeto de división en un subíndice:

    string[subscript]

El subíndice crea una porción al incluir dos puntos dentro de las llaves:

string[start:stop:step]

Para crear una división fuera de las llaves, deberá crear un objeto de división:

slice_obj = slice(start, stop, step) string[slice_obj]

Un enfoque legible:

Mientras que ''''.join(reversed(''foo'')) es legible, requiere llamar a un método de cadena, str.join , en otra función llamada, que puede ser relativamente lenta. Vamos a poner esto en una función, vamos a volver a ella:

def reverse_string_readable_answer(string): return ''''.join(reversed(string))

El enfoque más performante:

Mucho más rápido es usar un corte inverso:

''foo''[::-1]

Pero, ¿cómo podemos hacer que esto sea más legible y comprensible para alguien menos familiarizado con los cortes o la intención del autor original? Vamos a crear un objeto de división fuera de la notación de subíndice, asígnele un nombre descriptivo y pase a la notación de subíndice.

start = stop = None step = -1 reverse_slice = slice(start, stop, step) ''foo''[reverse_slice]

Implementar como Función

Para implementar esto como una función, creo que es semánticamente lo suficientemente claro como para usar simplemente un nombre descriptivo:

def reversed_string(a_string): return a_string[::-1]

Y el uso es simplemente:

reversed_string(''foo'')

Lo que tu profesor probablemente quiere:

Si tiene un instructor, es probable que quieran comenzar con una cadena vacía y construir una nueva cadena a partir de la anterior. Puedes hacer esto con sintaxis pura y literales usando un bucle while:

def reverse_a_string_slowly(a_string): new_string = '''' index = len(a_string) while index: index -= 1 # index = index - 1 new_string += a_string[index] # new_string = new_string + character return new_string

Esto es teóricamente malo porque, recuerde, las cadenas son inmutables , por lo que cada vez que parece que está agregando un carácter a su nueva cadena, ¡en teoría, está creando una nueva cadena cada vez! Sin embargo, CPython sabe cómo optimizar esto en ciertos casos, de los cuales este caso trivial es uno.

Mejores prácticas

Teóricamente mejor es recopilar las subcadenas en una lista y unirlas más adelante:

def reverse_a_string_more_slowly(a_string): new_strings = [] index = len(a_string) while index: index -= 1 new_strings.append(a_string[index]) return ''''.join(new_strings)

Sin embargo, como veremos en los horarios a continuación para CPython, esto en realidad lleva más tiempo, porque CPython puede optimizar la concatenación de cadenas.

Tiempos

Aquí están los horarios:

>>> a_string = ''amanaplanacanalpanama'' * 10 >>> min(timeit.repeat(lambda: reverse_string_readable_answer(a_string))) 10.38789987564087 >>> min(timeit.repeat(lambda: reversed_string(a_string))) 0.6622700691223145 >>> min(timeit.repeat(lambda: reverse_a_string_slowly(a_string))) 25.756799936294556 >>> min(timeit.repeat(lambda: reverse_a_string_more_slowly(a_string))) 38.73570013046265

CPython optimiza la concatenación de cadenas, mientras que otras implementaciones pueden no :

... no confíe en la implementación eficiente de CPython de la concatenación de cadenas en el lugar para las declaraciones en la forma a + = b o a = a + b. Esta optimización es frágil incluso en CPython (solo funciona para algunos tipos) y no está presente en absoluto en implementaciones que no usan refcounting. En las partes de la biblioteca sensibles al rendimiento, se debe utilizar el formulario '''' .join () en su lugar. Esto asegurará que la concatenación ocurra en tiempo lineal en varias implementaciones.


Respuesta rápida (TL; DR)

Ejemplo

### example01 ------------------- mystring = ''coup_ate_grouping'' backwards = mystring[::-1] print backwards ### ... or even ... mystring = ''coup_ate_grouping''[::-1] print mystring ### result01 ------------------- '''''' gnipuorg_eta_puoc ''''''

Respuesta detallada

Fondo

Esta respuesta se proporciona para abordar la siguiente inquietud de @odigity:

Guau. Al principio me horroricé por la solución que propuso Paolo, pero eso me hizo retroceder ante el horror que sentí al leer el primer comentario: "Eso es muy pitónico. ¡Buen trabajo!" Estoy tan perturbado que una comunidad tan brillante cree que usar métodos tan crípticos para algo tan básico es una buena idea. ¿Por qué no es sólo en el reverso ()?

Problema

  • Contexto
    • Python 2.x
    • Python 3.x
  • Guión:
    • El desarrollador quiere transformar una cadena
    • La transformación es invertir el orden de todos los personajes.

Solución

Escollos

  • El desarrollador podría esperar algo como string.reverse()
  • La solución idiomática nativa (también conocida como " pythonic ") puede no ser legible para los desarrolladores más nuevos
  • El desarrollador puede tener la tentación de implementar su propia versión de string.reverse() para evitar la notación de segmento.
  • La salida de notación de segmento puede ser contraintuitiva en algunos casos:
    • ver por ejemplo, ejemplo02
      • print ''coup_ate_grouping''[-4:] ## => ''ping''
      • comparado con
      • print ''coup_ate_grouping''[-4:-1] ## => ''pin''
      • comparado con
      • print ''coup_ate_grouping''[-1] ## => ''g''
    • Los diferentes resultados de la indexación en [-1] pueden echar a algunos desarrolladores

Razón fundamental

Python tiene una circunstancia especial a tener en cuenta: una cadena es un tipo iterable .

Una razón para excluir un método string.reverse() es dar a los desarrolladores de Python incentivos para aprovechar el poder de esta circunstancia especial.

En términos simplificados, esto simplemente significa que cada carácter individual en una cadena puede operarse fácilmente como parte de una disposición secuencial de elementos, al igual que las matrices en otros lenguajes de programación.

Para entender cómo funciona esto, revisar example02 puede proporcionar una buena visión general.

Ejemplo02

### example02 ------------------- ## start (with positive integers) print ''coup_ate_grouping''[0] ## => ''c'' print ''coup_ate_grouping''[1] ## => ''o'' print ''coup_ate_grouping''[2] ## => ''u'' ## start (with negative integers) print ''coup_ate_grouping''[-1] ## => ''g'' print ''coup_ate_grouping''[-2] ## => ''n'' print ''coup_ate_grouping''[-3] ## => ''i'' ## start:end print ''coup_ate_grouping''[0:4] ## => ''coup'' print ''coup_ate_grouping''[4:8] ## => ''_ate'' print ''coup_ate_grouping''[8:12] ## => ''_gro'' ## start:end print ''coup_ate_grouping''[-4:] ## => ''ping'' (counter-intuitive) print ''coup_ate_grouping''[-4:-1] ## => ''pin'' print ''coup_ate_grouping''[-4:-2] ## => ''pi'' print ''coup_ate_grouping''[-4:-3] ## => ''p'' print ''coup_ate_grouping''[-4:-4] ## => '''' print ''coup_ate_grouping''[0:-1] ## => ''coup_ate_groupin'' print ''coup_ate_grouping''[0:] ## => ''coup_ate_grouping'' (counter-intuitive) ## start:end:step (or start:end:stride) print ''coup_ate_grouping''[-1::1] ## => ''g'' print ''coup_ate_grouping''[-1::-1] ## => ''gnipuorg_eta_puoc'' ## combinations print ''coup_ate_grouping''[-1::-1][-4:] ## => ''puoc''

Conclusión

La carga cognitiva asociada con la comprensión de cómo funciona la notación de corte en Python puede ser demasiado para algunos adoptadores y desarrolladores que no desean invertir mucho tiempo en aprender el idioma.

Sin embargo, una vez que se entienden los principios básicos, el poder de este enfoque sobre los métodos de manipulación de cadenas fijas puede ser bastante favorable.

Para aquellos que piensan de otra manera, existen enfoques alternativos, como las funciones lambda, los iteradores o las declaraciones de funciones únicas simples.

Si lo desea, un desarrollador puede implementar su propio método string.reverse (), sin embargo, es bueno entender la razón detrás de este aspecto de python.

Ver también


usando notación de corte

def rev_string(s): return s[::-1]

usando la función invertida ()

def rev_string(s): return ''''.join(reversed(s))

usando recursion

def rev_string(s): if len(s) == 1: return s return s[-1] + rev_string(s[:-1])


Aquí está simplemente:

Imprimir "loremipsum" [- 1 :: - 1]

y algunos lógicamente:

def str_reverse_fun(): empty_list = [] new_str = ''loremipsum'' index = len(new_str) while index: index = index - 1 empty_list.append(new_str[index]) return ''''.join(empty_list) print str_reverse_fun()

salida:

muspimerol


Aquí hay uno no lujoso:

def reverse(text): r_text = '''' index = len(text) - 1 while index >= 0: r_text += text[index] #string canbe concatenated index -= 1 return r_text print reverse("hello, world!")


Aquí hay uno sin [::-1] o reversed (para fines de aprendizaje):

def reverse(text): new_string = [] n = len(text) while (n > 0): new_string.append(text[n-1]) n -= 1 return ''''.join(new_string) print reverse("abcd")

puede usar += para concatenar cadenas, pero join() es más rápido.


Claro, en Python puedes hacer cosas muy elegantes de 1 línea. :)
Aquí hay una solución simple y completa que podría funcionar en cualquier lenguaje de programación.

def reverse_string(phrase): reversed = "" length = len(phrase) for i in range(length): reversed += phrase[length-1-i] return reversed phrase = raw_input("Provide a string: ") print reverse_string(phrase)


El s[::-1] de Paolo s[::-1] es el más rápido; un enfoque más lento (quizás más legible, pero eso es discutible) es ''''.join(reversed(s)) .


Esa es mi manera:

def reverse_string(string): character_list = [] for char in string: character_list.append(char) reversed_string = "" for char in reversed(character_list): reversed_string += char return reversed_string


Esta es también una forma interesante:

def reverse_words_1(s): rev = '''' for i in range(len(s)): j = ~i # equivalent to j = -(i + 1) rev += s[j] return rev

o similar:

def reverse_words_2(s): rev = '''' for i in reversed(range(len(s)): rev += s[i] return rev

Otra forma más ''exótica'' usando byterarray que soporta .reverse ()

b = byterarray(''Reverse this!'', ''UTF-8'') b.reverse() b.decode(''UTF-8'')`

Producirá:

''!siht esreveR''


Esta es una función inversa simple y significativa, fácil de entender y codificar

def reverse_sentence(text): words = text.split(" ") reverse ="" for word in reversed(words): reverse += word+ " " return reverse


Invierta una cadena en python sin usar reversed () o [:: - 1]

def reverse(test): n = len(test) x="" for i in range(n-1,-1,-1): x += test[i] return x


Método recursivo:

def reverse(s): return s[0] if len(s)==1 else s[len(s)-1] + reverse(s[0:len(s)-1])

ejemplo:

print(reverse("Hello!")) #!olleH


Otra alternativa (¡no es eficiente, solo para mostrar la diversidad de Python con tantas soluciones posibles!): Convierta la cadena a una lista usando la función list (). Un valor de lista es un tipo de datos mutable. Por lo tanto, podemos usar el método reverse () que invierte los objetos de una lista en su lugar. Y luego convertimos la lista de nuevo a una cadena usando el método de unión de lista con un separador vacío:

>>> s = ''hello world'' >>> s ''hello world'' >>> t = list(s) # convert to list >>> t [''h'', ''e'', ''l'', ''l'', ''o'', '' '', ''w'', ''o'', ''r'', ''l'', ''d''] >>> t.reverse() # reverse method of list >>> t [''d'', ''l'', ''r'', ''o'', ''w'', '' '', ''o'', ''l'', ''l'', ''e'', ''h''] >>> s = ''''.join(t) # convert to string >>> s ''dlrow olleh''


Otra forma utilizando enumerar :

def reverse_string(string): s = '''' for i, char in enumerate(string[::-1]): s +=char return s


Puede utilizar la función invertida con una lista comprehesive. Pero no entiendo por qué este método fue eliminado en python 3, fue innecesariamente.

string = [ char for char in reversed(string)]


Qué tal si:

>>> ''hello world''[::-1] ''dlrow olleh''

Esta es la sintaxis de la porción extendida . Funciona al hacer [begin:end:step] ; al dejar begin y end y especificando un paso de -1, invierte una cadena.


Todas las soluciones anteriores son perfectas, pero si estamos tratando de revertir una cadena usando for loop en python se volverá un poco complicado, así es como podemos revertir una cadena usando for loop

string ="hello,world" for i in range(-1,-len(string)-1,-1): print (string[i],end=(" "))

Espero que este sea de ayuda para alguien.


Una manera menos perpleja de verlo sería:

string = ''happy'' print(string)

''feliz''

string_reversed = string[-1::-1] print(string_reversed)

''yppah''

En inglés [-1 :: - 1] se lee como:

"Comenzando en -1, sigue todo el camino, tomando pasos de -1"


s = ''Hola mundo''

s [:: - 1]

en el ejemplo anterior, la etiqueta s o la variable s contiene una cadena que contiene la cadena Hello world y, en el segundo paso, imprimo el reverso de la cadena Hello world al comenzar desde todo a todo en el orden de paso inverso con -1.


def rev(str1): print( str1[::-1]) str1="123" r=rev(str1)


def reverse(input): return reduce(lambda x,y : y+x, input)


s = ''hello'' ln = len(s) i = 1 while True: rev = s[ln-i] print rev, i = i + 1 if i == ln + 1 : break

SALIDA:

o l l e h