Frage Kehren Sie eine Zeichenfolge in Python um


Es ist nicht eingebaut reverse Funktion für Pythons str Objekt. Was ist der beste Weg, diese Methode zu implementieren?

Wenn Sie eine sehr knappe Antwort geben, erläutern Sie bitte deren Effizienz. Zum Beispiel, ob die str Objekt wird in ein anderes Objekt umgewandelt usw.


1069
2018-05-31 02:10


Ursprung


Antworten:


Wie wäre es mit:

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

Das ist erweiterte Scheibe Syntax. Es funktioniert so [begin:end:step] - indem Sie beginnen und enden und einen Schritt von -1 angeben, wird eine Zeichenkette umgekehrt.


2216
2018-05-31 02:11



@ Paolo's s[::-1] ist am schnellsten; ein langsamer Ansatz (vielleicht besser lesbar, aber das ist fraglich) ist ''.join(reversed(s)).


217
2018-05-31 02:13



Was ist der beste Weg, eine Umkehrfunktion für Strings zu implementieren?

Meine eigene Erfahrung mit dieser Frage ist akademisch. Wenn Sie jedoch ein Profi sind, der nach der schnellen Antwort sucht, verwenden Sie ein Stück, das vorbeigeht -1:

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

oder lesbarer (aber langsamer aufgrund der Methodennamensuche und der Tatsache, dass Join eine Liste bildet, wenn ein Iterator angegeben wird), str.join:

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

oder für die Lesbarkeit und Wiederverwendbarkeit, setzen Sie die Scheibe in eine Funktion

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

und dann:

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

Längere Erklärung

Wenn Sie an der wissenschaftlichen Ausstellung interessiert sind, lesen Sie bitte weiter.

Es gibt keine integrierte Umkehrfunktion in Pythons str-Objekt.

Hier sind ein paar Dinge über Pythons Strings, die Sie kennen sollten:

  1. In Python, Strings sind unveränderlich. Durch das Ändern einer Zeichenfolge wird die Zeichenfolge nicht geändert. Es schafft ein neues.

  2. Saiten sind schneidbar. Wenn Sie eine Saite schneiden, erhalten Sie eine neue Saite von einem Punkt in der Saite, rückwärts oder vorwärts, zu einem anderen Punkt, in bestimmten Schritten. Sie nehmen Slice-Notation oder ein Slice-Objekt in einem Index:

    string[subscript]
    

Der Index erstellt ein Segment, indem ein Doppelpunkt in die geschweiften Klammern eingefügt wird:

    string[start:stop:step]

Um ein Segment außerhalb der geschweiften Klammern zu erstellen, müssen Sie ein Segmentobjekt erstellen:

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

Ein lesbarer Ansatz:

Während ''.join(reversed('foo')) lesbar ist, erfordert es eine String-Methode aufrufen, str.join, auf einer anderen aufgerufenen Funktion, die eher relativ langsam sein kann. Lassen Sie uns das in eine Funktion bringen - wir werden darauf zurückkommen:

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

Meistens performanter Ansatz:

Viel schneller ist die Verwendung eines umgekehrten Slices:

'foo'[::-1]

Aber wie können wir dies für jemanden lesbarer und verständlicher machen, der mit Scheiben oder der Absicht des ursprünglichen Autors weniger vertraut ist? Lassen Sie uns ein Slice-Objekt außerhalb der tiefgestellten Notation erstellen, geben Sie ihm einen beschreibenden Namen und übergeben Sie es an die tiefgestellte Notation.

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

Als Funktion implementieren

Um dies tatsächlich als eine Funktion zu implementieren, denke ich, dass es semantisch klar genug ist, um einfach einen beschreibenden Namen zu verwenden:

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

Und die Verwendung ist einfach:

reversed_string('foo')

Was dein Lehrer wahrscheinlich will:

Wenn Sie einen Kursleiter haben, möchten Sie wahrscheinlich, dass Sie mit einer leeren Zeichenfolge beginnen und eine neue Zeichenfolge aus der alten erstellen. Sie können dies mit reiner Syntax und Literalen mit einer while-Schleife tun:

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

Das ist theoretisch schlecht, weil, erinnere dich, Strings sind unveränderlich - Jedes Mal, wenn es so aussieht, als würdest du einen Charakter an deinen hängen new_string, es erzeugt theoretisch jedes Mal eine neue Saite! CPython weiß jedoch, wie man dies in bestimmten Fällen, von denen dieser triviale Fall ist, optimiert.

Beste Übung

Theoretisch besser ist es, Ihre Teilstrings in einer Liste zu sammeln und sie später zu verbinden:

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)

Wie wir jedoch in den Zeitpunkten für CPython sehen werden, dauert dies länger, da CPython die String-Verkettung optimieren kann.

Zeiten

Hier sind die Zeiten:

>>> 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 optimiert String-Verkettung, während andere Implementierungen nicht dürfen:

... verlassen Sie sich nicht auf CPythons effiziente Implementierung der In-Place-String-Verkettung für Anweisungen in der Form a + = b oder a = a + b. Diese Optimierung ist selbst in CPython fragil (sie funktioniert nur bei einigen Typen) und ist in Implementierungen, die Refcounting nicht verwenden, überhaupt nicht vorhanden. In leistungssensitiven Teilen der Bibliothek sollte stattdessen das Formular ".join ()" verwendet werden. Dadurch wird sichergestellt, dass die Verkettung über verschiedene Implementierungen linear erfolgt.


168
2018-01-08 15:32



Schnelle Antwort (TL; DR)

Beispiel

### example01 -------------------
mystring  =   'coup_ate_grouping'
backwards =   mystring[::-1]
print backwards

### ... or even ...
mystring  =   'coup_ate_grouping'[::-1]
print mystring

### result01 -------------------
'''
gnipuorg_eta_puoc
'''

Ausführliche Antwort

Hintergrund

Diese Antwort wird bereitgestellt, um folgende Probleme von @odigity zu beheben:

Beeindruckend. Ich war zuerst entsetzt über die von Paolo vorgeschlagene Lösung, aber das   trat zurück zu dem Entsetzen, das ich beim Lesen der ersten fühlte   Kommentar: "Das ist sehr pythonisch. Gute Arbeit!" Ich bin so gestört, dass solche   Eine helle Community denkt mit solchen kryptischen Methoden nach so etwas   Basic ist eine gute Idee. Warum ist es nicht nur an Reverse ()?

Problem

  • Kontext
    • Python 2.x
    • Python 3.x
  • Szenario:
    • Entwickler möchte eine Zeichenfolge transformieren
    • Die Transformation besteht darin, die Reihenfolge aller Zeichen umzukehren

Lösung

Fallstricke

  • Entwickler könnte etwas wie erwarten string.reverse()
  • Die native idiomatische (aka "pythonisch") Lösung ist möglicherweise für neuere Entwickler nicht lesbar
  • Der Entwickler könnte versucht sein, seine eigene Version von string.reverse() um die Slice-Notation zu vermeiden.
  • Die Ausgabe der Slice-Notation kann in einigen Fällen kontraintuitiv sein:
    • siehe z.B. Beispiel02
      • print 'coup_ate_grouping'[-4:] ## => 'ping'
      • verglichen mit
      • print 'coup_ate_grouping'[-4:-1] ## => 'pin'
      • verglichen mit
      • print 'coup_ate_grouping'[-1] ## => 'g'
    • die verschiedenen Ergebnisse der Indexierung auf [-1] kann einige Entwickler abwerfen

Begründung

Python muss besondere Umstände beachten: Eine Zeichenkette ist eine iterierbar Art.

Eine Begründung für den Ausschluss von a string.reverse() Methode besteht darin, Python-Entwicklern einen Anreiz zu geben, die Macht dieses besonderen Umstandes zu nutzen.

Vereinfacht ausgedrückt bedeutet dies einfach, dass jedes einzelne Zeichen in einer Zeichenfolge als Teil einer sequentiellen Anordnung von Elementen einfach bearbeitet werden kann, genau wie Arrays in anderen Programmiersprachen.

Um zu verstehen, wie dies funktioniert, kann reviewing02 einen guten Überblick geben.

Beispiel02

### 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'

Fazit

Das kognitive Belastung Das Verständnis dafür, wie die Slice-Notation in Python funktioniert, mag für manche Adoptierer und Entwickler, die nicht viel Zeit in das Erlernen der Sprache investieren wollen, tatsächlich zu groß sein.

Sobald jedoch die Grundprinzipien verstanden sind, kann die Stärke dieses Ansatzes im Vergleich zu festen String-Manipulationsmethoden ziemlich günstig sein.

Für diejenigen, die anders denken, gibt es alternative Ansätze, wie Lambda-Funktionen, Iteratoren oder einfache einmalige Funktionsdeklarationen.

Falls gewünscht, kann ein Entwickler seine eigene string.reverse () -Methode implementieren, jedoch ist es gut, die Gründe für diesen Aspekt von Python zu verstehen.

Siehe auch


33
2017-10-31 22:24



Eine weniger verwirrende Art, es zu betrachten, wäre:

string = 'happy'
print(string)

'glücklich'

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

'Yppah'

In Englisch [-1 :: - 1] lautet wie folgt:

"Beginnen Sie bei -1, gehen Sie den ganzen Weg und machen Sie Schritte von -1"


10
2018-04-01 07:49



Umkehren einer Zeichenfolge in Python ohne Verwendung von reversed () oder [:: - 1]

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

4
2017-12-10 12:57



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

3
2018-06-26 04:25



Verwenden der Slice-Notation

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

mit der Funktion reversed ()

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

Rekursion verwenden

def rev_string(s): 
    if len(s) == 1:
        return s

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

3
2018-05-20 22:24