web-dev-qa-db-fra.com

Inverser une chaîne sans utiliser reverse () ou [:: - 1]?

Je suis tombé sur un étrange exercice de Codecademy qui nécessitait une fonction qui prendrait une chaîne en entrée et la renverrait dans l'ordre inverse. Le seul problème était que vous ne pouviez pas utiliser la méthode inversée ou la réponse commune ici sur stackoverflow, [::-1].

Évidemment, dans le monde réel de la programmation, on utiliserait probablement la méthode slice étend , ou même la fonction reversed, mais il y a peut-être un cas où cela ne fonctionnerait pas?

Je présente ci-dessous une solution sous la forme de questions-réponses, au cas où elle serait utile aux personnes futures.

39
samrap

Vous pouvez aussi le faire avec la récursivité:

def reverse(text):
    if len(text) <= 1:
        return text

    return reverse(text[1:]) + text[0]

Et un exemple simple pour la chaîne hello:

   reverse(hello)
 = reverse(Ello) + h           # The recursive step
 = reverse(llo) + e + h
 = reverse(lo) + l + e + h
 = reverse(o) + l + l + e + h  # Base case
 = o + l + l + e + h
 = olleh
62
Blender

Juste une autre option:

from collections import deque
def reverse(iterable):
    d = deque()
    d.extendleft(iterable)
    return ''.join(d)
18
Jon Clements

EDIT

L'activité récente sur cette question m'a amené à regarder en arrière et à changer ma solution en un one-liner rapide utilisant un générateur:

rev = ''.join([text[len(text) - count] for count in xrange(1,len(text)+1)])

Bien sûr, il y a de meilleures réponses ici, comme un pas négatif dans la fonction range ou xrange. Ce qui suit est ma solution d'origine:


Voici ma solution, je vais l'expliquer étape par étape

def reverse(text):

    lst = []
    count = 1

    for i in range(0,len(text)):

        lst.append(text[len(text)-count])
        count += 1

    lst = ''.join(lst)
    return lst

print reverse('hello')

Tout d'abord, nous devons passer un paramètre à la fonction, dans ce cas text.

Ensuite, j'ai défini une liste vide, nommée lst à utiliser ultérieurement. (En fait, je ne savais pas que j'aurais besoin de la liste avant d'arriver à la boucle for, vous verrez pourquoi c'est nécessaire dans une seconde.)

La variable count aura un sens une fois que je serai dans la boucle for

Jetons donc un coup d'œil à une version de base de ce que nous essayons d'accomplir:

Il est logique d’ajouter le dernier caractère à la liste en commençant par l’ordre inverse. Par exemple:

>>lst = []
>>Word = 'foo'
>>lst.append(Word[2])
>>print lst
['o']

Mais pour continuer à inverser l'ordre, nous devons ensuite ajouter Word[1] Puis Word[0]:

>>lst.append(Word[2])
>>lst.append(Word[1])
>>lst.append(Word[0])
>>print lst
['o','o','f']

C’est très bien. Nous avons maintenant une liste qui contient notre mot original dans l’ordre inverse et qui peut être reconverti en chaîne en utilisant .join(). Mais il y a un problème. Cela fonctionne pour le mot foo, cela fonctionne même pour n'importe quel mot qui a une longueur de 3 caractères. Mais qu'en est-il d'un mot avec 5 caractères? Ou 10 personnages? Maintenant ça ne marchera pas. Et s'il y avait un moyen de changer dynamiquement l'index que nous ajoutons pour que tout mot soit retourné dans l'ordre inverse?

Entrez pour la boucle.

for i in range(0,len(text)):

    lst.append(text[len(text)-count])
    count += 1

Tout d'abord, il est nécessaire d'utiliser in range() plutôt que simplement in, car nous devons parcourir les caractères du mot, mais nous devons également extraire la valeur d'index du mot afin que nous changeons l'ordre.

La première partie du corps de notre boucle for devrait paraître familière. C'est très semblable à

>>lst.append(Word[..index..])

En fait, le concept de base est exactement le même:

>>lst.append(text[..index..])

Alors, que font tous les trucs au milieu?

Eh bien, nous devons d’abord ajouter l’index de la dernière lettre à notre liste, qui est la longueur du mot, text, -1. A partir de maintenant, nous l'appellerons l(t) -1

>>lst.append(text[len(text)-1])

Cela seul recevra toujours la dernière lettre de notre mot et l'ajoutera à lst, quelle que soit la longueur du mot. Mais maintenant que nous avons la dernière lettre, qui est l(t) - 1, nous avons besoin de l’avant-dernière lettre, qui est l(t) - 2, et ainsi de suite, jusqu'à ce qu'il n'y ait plus de caractères à ajouter à la liste. N'oubliez pas notre variable count ci-dessus? Cela vous sera utile. En utilisant une boucle for, nous pouvons incrémente la valeur de count de 1 à chaque itération, de sorte que la valeur soustraite augmente jusqu'à ce que la boucle for ait parcouru le mot entier:

>>for i in range(0,len(text)):
..        
..      lst.append(text[len(text)-count])
..      count += 1

Maintenant que nous avons le cœur de notre fonction, regardons ce que nous avons jusqu'à présent:

def reverse(text):

    lst = []
    count = 1

    for i in range(0,len(text)):

        lst.append(text[len(text)-count])
        count += 1

Nous avons presque fini! À l'heure actuelle, si nous appelions notre fonction avec le mot "bonjour", nous obtiendrions une liste qui ressemblerait à ceci:

['o', 'l', 'l', 'e', ​​'h']

Nous ne voulons pas de liste, nous voulons une chaîne. Nous pouvons utiliser .join Pour cela:

def reverse(text):

    lst = []
    count = 1

    for i in range(0,len(text)):

        lst.append(text[len(text)-count])
        count += 1

    lst = ''.join(lst) # join the letters together without a space
    return lst

Et c'est tout. Si nous appelons le mot 'hello' à reverse (), nous obtiendrons ceci:

>>print reverse('hello')
olleh

Évidemment, c'est beaucoup plus de code que nécessaire dans une situation réelle. L'utilisation de la fonction inversée ou de la tranche étendue serait le moyen optimal d'accomplir cette tâche, mais il y a peut-être des cas où cela ne fonctionnerait pas et vous en auriez besoin. Quoi qu'il en soit, je pensais que je le partagerais avec quiconque serait intéressé.

Si vous avez d'autres idées, j'aimerais les entendre!

11
samrap

Utilisez les instructions inversées range:

def reverse(strs):
    for i in xrange(len(strs)-1, -1, -1):
        yield strs[i]
...         
>>> ''.join(reverse('hello'))
'olleh'

xrange ou range avec -1 pas renverrait les éléments dans l'ordre inverse, nous devons donc itérer de len(string)-1 à -1 (exclusif) et récupérer des éléments de la chaîne un par un.

>>> list(xrange(len(strs) -1, -1 , -1))
[4, 3, 2, 1, 0]  #iterate over these indexes and fetch the items from the string

Bon mot:

def reverse(strs):
    return ''.join([strs[i] for i in xrange(len(strs)-1, -1, -1)])
... 
>>> reverse('hello')
'olleh'
11
Ashwini Chaudhary

N’a codé que Python pendant quelques jours, mais j’estime qu’il s’agissait d’une solution assez propre. Créez une liste vide, parcourez chaque lettre de la chaîne et ajoutez-la au début de la liste. , retourne la liste des membres sous forme de chaîne.

def reverse(text):
backwardstext = []
for letter in text:
    backwardstext.insert(0, letter)
return ''.join(backwardstext)
7
user3355359

J'ai utilisé ceci:

def reverse(text):
s=""
l=len(text)
for i in range(l):
    s+=text[l-1-i]
return s
5
Sumit Kushwaha

C'est une question très intéressante, j'aimerai offrir une réponse simple:

>>> S='abcdefg'
>>> ''.join(item[1] for item in sorted(enumerate(S), reverse=True))
'gfedcba'

Brève explication:

enumerate() renvoie [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g')]. Les indices et les valeurs. Pour inverser les valeurs, il suffit de trier en sens inverse par sorted(). Enfin, rassemblez-le pour créer un str

4
CT Zhu

Inspiré par la réponse de Jon, que diriez-vous de celle-ci

Word = 'hello'
q = deque(Word)
''.join(q.pop() for _ in range(len(Word)))
4
Burhan Khalid
reduce(lambda x, y : y + x, "hello world")
3
Vinod Puliyadi

J'ai créé différentes versions pour inverser une chaîne dans python dans mon référentiel: https://github.com/fedmich/Python-Codes/tree/master/Reverse%20a % 20String

Vous pouvez le faire en utilisant list-comprehension ou technique lambda :

# Reverse a string without using reverse() function
s = 'Federico';
li = list( s )  #convert string to list

ret = [ li[i-1] for i in xrange(len(li),0,-1)  ]    #1 liner lambda
print ( "".join( ret ) )

ou en faisant un en arrière pour la boucle

# Reverse a string without using reverse() function
s = 'Federico';
r = []

length = len(s)
for i in xrange(length,0,-1):
    r.append( s[ i - 1] )

print ( "".join(r) )
3
fedmich
def reverse(s):
    return "".join(s[i] for i in range(len(s)-1, -1, -1))
2
CrackSmoker9000

je viens de résoudre ceci dans l'académie de code et vérifiais mes réponses et courais à travers cette liste. donc, avec une compréhension très limitée de python), je viens de faire cela et cela a fonctionné.

def reverse(s):
    i = len(s) - 1
    sNew = ''
    while  i >= 0:
        sNew = sNew + str(s[i])
        i = i -1
    return sNew
2
dewetha

Une version jouée au golf: r=lambda x:"".join(x[i] for i in range(len(x-1),-1,-1)).

2
rlms

La réponse de Blender est charmante, mais pour une très longue chaîne, il en résultera un énorme RuntimeError: maximum recursion depth exceeded. On peut refactoriser le même code dans une boucle while, comme on doit souvent le faire avec la récursivité en python. De toute évidence toujours mauvais en raison de problèmes de temps et de mémoire, mais au moins ne sera pas une erreur.

def reverse(text):
    answer = ""
    while text:
        answer = text[0] + answer
        text = text[1:]
    return answer
2
mehtunguh

Tout ce que j'ai fait pour obtenir une chaîne inversée est d'utiliser la fonction xrange avec la longueur de la chaîne dans une boucle for et de revenir en arrière de la manière suivante:

myString = "ABC"

for index in xrange(len(myString),-1):
    print index

Ma sortie est "CBA"

1
usuariodesconocido

Vous pouvez simplement inverser votre chaîne en commençant par le dernier caractère. Avec python, vous pouvez utiliser la compréhension de liste pour construire la liste de caractères dans l'ordre inverse, puis les joindre pour obtenir la chaîne inversée dans une ligne:

def reverse(s):
  return "".join([s[-i-1] for i in xrange(len(s))])

si vous n'êtes même pas autorisé à utiliser l'indexation négative, remplacez s[-i-1] par s[len(s)-i-1]

1
Emanuele Paolini

Voici ma solution utilisant la boucle for in in range:

def reverse(string):
    tmp = ""
    for i in range(1,len(string)+1):
        tmp += string[len(string)-i]            
    return tmp

C'est assez facile à comprendre. Je pars de 1 pour éviter l'index hors limite.

1
Stefano Saitta

Je viens également de résoudre l'exercice corespondant sur la codéacademie et je voulais comparer mon approche aux autres. Je n’ai pas trouvé la solution que j’avais utilisée jusqu’à présent, alors j’ai pensé que j’étais inscrit ici et que je fournissais ma solution à d’autres. Et peut-être que je reçois une suggestion ou un commentaire utile sur la façon d’améliorer le code.

Ok voilà, je n'ai utilisé aucune liste pour stocker la chaîne, à la place je viens d'accéder à l'index de chaîne. Il m'a fallu un peu au début pour m'occuper du len () et du numéro d'index, mais à la fin cela a fonctionné :).

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

Je me demande encore si le reversestring = "" pourrait être résolu de manière plus élégante, ou même si c'est "mauvais style", mais je n'ai pas trouvé de réponse pour l'instant.

1
Fadeiar

En voici une qui utilise une liste en pile:

def reverse(s):
  rev = [_t for _t in s]
  t = ''
  while len(rev) != 0:
    t+=rev.pop()
  return t
1
user2399453

Vous pouvez faire simplement comme ça

def rev(str):
   rev = ""
   for i in range(0,len(str)):
   rev = rev + str[(len(str)-1)-i]
   return rev
1
Vijay
def reverseThatString(theString):
    reversedString = ""
    lenOfString = len(theString)
    for i,j in enumerate(theString):
        lenOfString -= 1
        reversedString += theString[lenOfString]
    return reversedString
1
mattshirtliffe

C'est une façon de le faire avec une boucle while:

def reverse(s):
    t = -1
    s2 = ''
    while abs(t) < len(s) + 1: 
        s2 = s2 + s[t]
        t  = t - 1
    return s2
1
PythonSam
def reverse(text):
    a=""
    l=len(text)
    while(l>=1):
        a+=text[l-1]
        l-=1
    return a

je viens de concaténer la chaîne a avec les index de texte les plus élevés (qui continue à décrémenter de 1 chaque boucle).

1

Aujourd'hui, le même exercice sur papier et stylo m'a été demandé. Je propose donc cette fonction pour les listes:

def rev(s):
  l = len(s)
  for i,j in Zip(range(l-1, 0, -1), range(l//2)):
    s[i], s[j] = s[j], s[i]
  return s

qui peut être utilisé avec des chaînes avec "".join(rev(list("hello")))

1
berdario

Voici ma contribution:

def rev(test):  
    test = list(test)
    i = len(test)-1
    result = []

    print test
    while i >= 0:
        result.append(test.pop(i))
        i -= 1
    return "".join(result)
1
fra

Vous avez reçu beaucoup de réponses alternatives, mais juste pour ajouter une autre solution simple - la première chose qui vous est venue à l'esprit est la suivante:

def reverse(text):
    reversed_text = ""   

    for n in range(len(text)):
        reversed_text += text[-1 - n]

    return reversed_text

Ce n'est pas aussi rapide que certaines des autres options mentionnées par les gens (ou méthodes intégrées), mais facile à suivre car nous utilisons simplement la longueur de la chaîne text pour concaténer un caractère à la fois en découpant de la fin vers l'avant.

1
PerryAJ

Vous pouvez simplement utiliser la pop comme suggéré. Voici une doublure pour cela

chaine = 'qwertyuiop'
''.join([chaine[-(x + 1)] for x in range(len(chaine))])
'poiuytrewq'
gg = list(chaine)
''.join([gg.pop() for _ in range(len(gg))])
'poiuytrewq'
0
cgte

Ma solution:

s = raw_input ("Enter string")
impression
def reverse (text):

st = ""  
rev = ""  
count = len(text)  
print "Lenght of text: ", len(text)  
print  
for c in range(len(text)):  
    count = count - 1  
    st = st + "".join(text[c])  
    rev = rev + "".join(text[count])  
    print "count:       ", count  
    print "print c:     ", c  
    print "text[c]:     ", text[c]  
    print  
print "Original:    ", st  
print "Reversed:    ", rev  
return rev  

inverse (s)

Écran de résultat

Entrez chaîne joca

Longueur du texte: 4

compte: 3
print c: 0
texte [c]: j

compte: 2
print c: 1
texte [c]: o

compte: 1
print c: 2
texte [c]: c

compte: 0
print c: 3
texte [c]: a

Original: joca
Inversé: acoj
Aucun

0
Jovica

La façon dont je peux penser sans utiliser aucune fonction intégrée:

a = 'Word'
count = 0
for letter in a:
    count += 1

b = ''
for letter in a:
    b += a[count-1]
    count -= 1

Et si vous imprimez b:

print b
drow
0
Sunny Mui

C’est le moyen le plus simple de python 2.7

def reverse(text):

      rev = ""
      final = ""

      for a in range(0,len(text)):
            rev = text[len(text)-a-1]
            final = final + rev
return final
0
AceRam

Pas très intelligent, mais solution délicate

def reverse(t):
    for j in range(len(t) // 2):
        t = t[:j] + t[- j - 1] + t[j + 1:- j - 1] + t[j] + t[len(t) - j:]
    return t
0
Dmitry_Kovalov

Je préfère cela comme le meilleur moyen d’inverser une chaîne en utilisant une boucle for.

def reverse_a_string(str): 

    result=" "
    for i in range(len(str),1,-1):
        result= result+ str[i-1]
    return result

print reverse_a_string(input())
0
Kapilfreeman
enterString=input("Enter a string to be reversed:")
string_List=list(enterString)
revedString=[]

for i in range(len(string_List)):
    revedString.append(string_List.pop())
#Pop last element and append it to the empty list
print "reversed string is:",''.join(revedString)
#as the out come is in list convert it into string using .join

Sample Output:
>>>Enter a string to be reversed :sampleReverse1  
>>>reversed string is:1esreveRelpmas 
0
Sanyal

exécutez-le simplement, mais chaque caractère sera imprimé sur une ligne distincte et la deuxième version l’imprimera sur une seule ligne.

def rev(str):
        for i in range(0,len(str)):
            print(list(str)[len(str)-i-1])

Imprimer en une ligne:

def rev(str):
    rev = list()
    for i in range(0,len(str)):
        rev.append((list(str)[len(str)-i-1]))
    print(''.join(rev))
0
jax

Pointfree:

from functools import partial
from operator import add

flip = lambda f: lambda x, y: f(y, x)
rev = partial(reduce, flip(add))

Tester:

>>> rev('hello')
'olleh'
0
pillmuncher
m = input("Enter string::")
def rev(s):
    z = -1
    x = len(s)
    while x != 0:
        print(s[z], end='')
        z = z-1
        x = x-1
rev(m)
0
chandra

tu as assez de réponse.

Je veux juste partager une autre façon.

vous pouvez écrire deux petites fonctions pour reverse et comparer la sortie de la fonction avec la chaîne donnée

var = ''

def reverse (données):

for i in data:
    var = i + var
return var

sinon var == données:

imprimer "Pas de palindrome"

autre :

imprimer "Palindrome"

0
rajpython

Méthode simple

>>> a = "hi hello"
>>> ''.join([a[len(a)-i-1] for i,j in enumerate(a)])
'olleh ih'
>>> 
0