Diese Antwort ist etwas länger und enthält 3 Abschnitte: Benchmarks der bestehenden Lösungen, warum die meisten Lösungen hier falsch sind , meine Lösung .
Die vorhandenen Antworten sind nur korrekt, wenn Unicode-Modifikatoren / Graphem-Cluster ignoriert werden. Ich werde mich später damit befassen, aber zunächst einen Blick auf die Geschwindigkeit einiger Umkehralgorithmen werfen:
![enter image description here]()
list_comprehension : min: 0.6s, mean: 0.6s, max: 2.2s
reverse_func : min: 1.9s, mean: 2.0s, max: 7.9s
reverse_reduce : min: 5.7s, mean: 5.9s, max: 10.2s
reverse_loop : min: 3.0s, mean: 3.1s, max: 6.8s
![enter image description here]()
list_comprehension : min: 4.2s, mean: 4.5s, max: 31.7s
reverse_func : min: 75.4s, mean: 76.6s, max: 109.5s
reverse_reduce : min: 749.2s, mean: 882.4s, max: 2310.4s
reverse_loop : min: 469.7s, mean: 577.2s, max: 1227.6s
Sie können sehen, dass die Zeit für das Listenverständnis ( reversed = string[::-1]
) ist in allen Fällen bei weitem die niedrigste (auch nach Korrektur meines Tippfehlers).
String-Umkehrung
Wenn Sie eine Zeichenkette wirklich im allgemeinen Sinne umkehren wollen, ist es VIEL komplizierter. Nehmen wir zum Beispiel die folgende Zeichenkette ( brauner Finger, der nach links zeigt , gelber Finger nach oben zeigend ). Das sind zwei Grapheme, aber 3 Unicode-Codepunkte. Der zusätzliche Punkt ist ein Hautmodifikator .
example = ""
Aber wenn Sie es mit einer der angegebenen Methoden umkehren, erhalten Sie brauner Finger, der nach oben zeigt , gelber Finger zeigt nach links . Der Grund dafür ist, dass der Farbmodifikator "braun" immer noch in der Mitte liegt und auf alles, was davor liegt, angewendet wird. Wir haben also
- U: nach oben gerichteter Finger
- M: brauner Modifikator
- L: Finger zeigt nach links
und
original: LMU
reversed: UML (above solutions)
reversed: ULM (correct reversal)
Unicode Graphem-Cluster sind etwas komplizierter als nur Modifikatorcodepunkte. Glücklicherweise gibt es eine Bibliothek für den Umgang mit Grapheme :
>>> import grapheme
>>> g = grapheme.graphemes("")
>>> list(g)
['', '']
und daher wäre die richtige Antwort
def reverse_graphemes(string):
g = list(grapheme.graphemes(string))
return ''.join(g[::-1])
die auch bei weitem die langsamste ist:
list_comprehension : min: 0.5s, mean: 0.5s, max: 2.1s
reverse_func : min: 68.9s, mean: 70.3s, max: 111.4s
reverse_reduce : min: 742.7s, mean: 810.1s, max: 1821.9s
reverse_loop : min: 513.7s, mean: 552.6s, max: 1125.8s
reverse_graphemes : min: 3882.4s, mean: 4130.9s, max: 6416.2s
Der Kodex
#!/usr/bin/env python
import numpy as np
import random
import timeit
from functools import reduce
random.seed(0)
def main():
longstring = ''.join(random.choices("ABCDEFGHIJKLM", k=2000))
functions = [(list_comprehension, 'list_comprehension', longstring),
(reverse_func, 'reverse_func', longstring),
(reverse_reduce, 'reverse_reduce', longstring),
(reverse_loop, 'reverse_loop', longstring)
]
duration_list = {}
for func, name, params in functions:
durations = timeit.repeat(lambda: func(params), repeat=100, number=3)
duration_list[name] = list(np.array(durations) * 1000)
print('{func:<20}: '
'min: {min:5.1f}s, mean: {mean:5.1f}s, max: {max:6.1f}s'
.format(func=name,
min=min(durations) * 10**6,
mean=np.mean(durations) * 10**6,
max=max(durations) * 10**6,
))
create_boxplot('Reversing a string of length {}'.format(len(longstring)),
duration_list)
def list_comprehension(string):
return string[::-1]
def reverse_func(string):
return ''.join(reversed(string))
def reverse_reduce(string):
return reduce(lambda x, y: y + x, string)
def reverse_loop(string):
reversed_str = ""
for i in string:
reversed_str = i + reversed_str
return reversed_str
def create_boxplot(title, duration_list, showfliers=False):
import seaborn as sns
import matplotlib.pyplot as plt
import operator
plt.figure(num=None, figsize=(8, 4), dpi=300,
facecolor='w', edgecolor='k')
sns.set(style="whitegrid")
sorted_keys, sorted_vals = zip(*sorted(duration_list.items(),
key=operator.itemgetter(1)))
flierprops = dict(markerfacecolor='0.75', markersize=1,
linestyle='none')
ax = sns.boxplot(data=sorted_vals, width=.3, orient='h',
flierprops=flierprops,
showfliers=showfliers)
ax.set(xlabel="Time in ms", ylabel="")
plt.yticks(plt.yticks()[0], sorted_keys)
ax.set_title(title)
plt.tight_layout()
plt.savefig("output-string.png")
if __name__ == '__main__':
main()
0 Stimmen
Mögliches Duplikat von stackoverflow.com/questions/3940128/how-to-reverse-a-list
0 Stimmen
@Ender das Duplikat sollte auf die andere Frage sein, da diese schon älter ist.
0 Stimmen
"das Duplikat sollte auf der anderen Frage stehen, da diese einmal älter ist" Es funktioniert auf Stack Overflow eigentlich nicht so . Wir nutzen den Vorteil der Rückschau, um das zu wählen, was wir für das Beste halten. beste Version der Frage. Abgesehen davon funktionieren viele Techniken sowohl für eine Zeichenkette als auch für eine Liste, andere wiederum nicht, und es gibt auch keine klare Präferenz für die eine Frage gegenüber der anderen. Daher denke ich nicht, dass eine der beiden Fragen als Duplikat gekennzeichnet werden sollte.