Was ist die pythonischste Art, zwei Saiten miteinander zu verbinden?
Beispielsweise:
Eingang:
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
Ausgabe:
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
python
string
python-2.7
python-3.x
Brandon Deo
quelle
quelle
Antworten:
Für mich ist der pythonischste * Weg der folgende, der so ziemlich das Gleiche tut, aber den
+
Operator zum Verketten der einzelnen Zeichen in jeder Zeichenfolge verwendet:Es ist auch schneller als zwei
join()
Anrufe:Es gibt schnellere Ansätze, die den Code jedoch häufig verschleiern.
Hinweis: Wenn die beiden Eingabezeichenfolgen nicht dieselbe Länge haben, wird die längere abgeschnitten, da
zip
die Iteration am Ende der kürzeren Zeichenfolge stoppt. In diesem Fall stattzip
sollte man verwendenzip_longest
(izip_longest
in Python 2) aus demitertools
Modul , um sicherzustellen , dass beide Saiten voll ausgeschöpft werden.* Um ein Zitat aus dem Zen von Python zu erhalten : Lesbarkeit zählt .
Pythonic = Lesbarkeit für mich;
i + j
wird nur visuell leichter analysiert, zumindest für meine Augen.quelle
"".join([i + j for i, j in zip(l1, l2)])
und es wird definitiv das schnellste sein"".join(map("".join, zip(l1, l2)))
ist noch schneller, wenn auch nicht unbedingt pythonischer.Schnellere Alternative
Ein anderer Weg:
Ausgabe:
Geschwindigkeit
Sieht so aus, als wäre es schneller:
als die bisher schnellste Lösung:
Auch für die größeren Saiten:
Python 3.5.1.
Variation für Saiten unterschiedlicher Länge
Kürzere bestimmt Länge (
zip()
äquivalent)Ausgabe:
Länger bestimmt die Länge (
itertools.zip_longest(fillvalue='')
äquivalent)Ausgabe:
quelle
Mit
join()
undzip()
.quelle
''.join(itertools.chain.from_iterable(zip(u, l)))
zip
wenn die kürzere Liste vollständig durchlaufen wurde.itertools.zip_longest
kann verwendet werden, wenn es ein Problem wird.Unter Python 2 ist der weitaus schnellere Weg, Dinge zu erledigen, mit ~ 3x der Geschwindigkeit, mit der Listen für kleine Zeichenfolgen und ~ 30x für lange Zeichenfolgen geschnitten werden
Dies würde jedoch unter Python 3 nicht funktionieren. Sie könnten so etwas implementieren
Bis dahin haben Sie jedoch bereits die Vorteile des Listen-Slicing für kleine Zeichenfolgen verloren (es ist immer noch 20-mal so schnell wie für lange Zeichenfolgen), und dies funktioniert noch nicht einmal für Nicht-ASCII-Zeichen.
FWIW, wenn Sie werden diese auf massiven Saiten zu tun und müssen in jedem Zyklus, und aus irgendeinem Grund Python - Strings verwenden ... ist hier , wie es geht:
Ein spezielles Gehäuse, wie es bei kleineren Typen üblich ist, hilft ebenfalls. FWIW, dies ist nur das Dreifache der Geschwindigkeit des Listenschneidens für lange Zeichenfolgen und ein Faktor von 4 bis 5 langsamer für kleine Zeichenfolgen.
In beiden Fällen bevorzuge ich die
join
Lösungen, aber da die Timings an anderer Stelle erwähnt wurden, dachte ich, ich könnte genauso gut mitmachen.quelle
Wenn Sie den schnellsten Weg suchen , können Sie itertools kombinieren mit
operator.add
:Aber kombinieren
izip
undchain.from_iterable
ist wieder schnellerEs gibt auch einen wesentlichen Unterschied zwischen
chain(*
undchain.from_iterable(...
.Es gibt keinen Generator mit Join. Die Übergabe eines Generators wird immer langsamer, da Python zuerst eine Liste mit dem Inhalt erstellt, da zwei Durchgänge über die Daten ausgeführt werden, einer, um die erforderliche Größe zu ermitteln, und einer, um tatsächlich zu tun die Verknüpfung, die mit einem Generator nicht möglich wäre:
join.h :
Auch wenn Sie Zeichenfolgen unterschiedlicher Länge haben und keine Daten verlieren möchten, können Sie izip_longest verwenden :
Für Python 3 heißt es
zip_longest
Für python2 ist der Vorschlag von veedrac jedoch bei weitem der schnellste:
quelle
list
? wird nicht benötigt"".join(list(...))
gib mir 6.715280318699769 und timeit das"".join(starmap(...))
gib mir 6.46332361384313"".join(list(starmap(add, izip(l1,l2))))
das langsamer ist als"".join(starmap(add, izip(l1,l2)))
. Ich führe den Test auf meinem Computer in Python 2.7.11 und in Python 3.5.1 sogar in der virtuellen Konsole von www.python.org mit Python 3.4.3 aus und alle sagen dasselbe und ich führe ihn ein paar Mal und immer aus gleicheSie können dies auch mit
map
und tunoperator.add
:Ausgabe :
Map nimmt jedes Element aus der ersten Iterable
u
und die ersten Elemente aus der zweiten Iterablel
und wendet die als erstes Argument angegebene Funktion anadd
. Dann schließt sich ihnen einfach an.quelle
Jims Antwort ist großartig, aber hier ist meine Lieblingsoption, wenn Ihnen ein paar Importe nichts ausmachen:
quelle
Bei vielen dieser Vorschläge wird davon ausgegangen, dass die Zeichenfolgen gleich lang sind. Vielleicht deckt das alle vernünftigen Anwendungsfälle ab, aber zumindest scheint es mir, dass Sie auch Saiten unterschiedlicher Länge aufnehmen möchten. Oder bin ich der einzige, der denkt, das Netz sollte ein bisschen so funktionieren:
Ein Weg, dies zu tun, wäre der folgende:
quelle
Ich benutze gerne zwei
for
s, die Variablennamen können einen Hinweis / eine Erinnerung geben, was los ist:quelle
Nur um einen weiteren, grundlegenderen Ansatz hinzuzufügen:
quelle
Fühlt sich ein bisschen unpythonisch an, die Antwort auf das Doppellistenverständnis hier nicht zu berücksichtigen, um n Zeichenfolgen mit O (1) Aufwand zu behandeln:
Wo
all_strings
ist eine Liste der Zeichenfolgen, die Sie verschachteln möchten. In Ihrem Fallall_strings = [u, l]
. Ein Beispiel für eine vollständige Verwendung würde folgendermaßen aussehen:Wie viele Antworten am schnellsten? Wahrscheinlich nicht, aber einfach und flexibel. Ohne zu viel zusätzliche Komplexität ist dies etwas schneller als die akzeptierte Antwort (im Allgemeinen ist das Hinzufügen von Zeichenfolgen in Python etwas langsam):
quelle
Potenziell schneller und kürzer als die derzeit führende Lösung:
In Bezug auf die Geschwindigkeit besteht die Strategie darin, so viel wie möglich auf C-Ebene zu tun. Dieselbe zip_longest () - Korrektur für ungleichmäßige Zeichenfolgen und sie würde aus demselben Modul wie chain () stammen, kann mir also nicht zu viele Punkte geben!
Andere Lösungen, die ich mir auf dem Weg ausgedacht habe:
quelle
Sie könnten 1 verwenden
iteration_utilities.roundrobin
oder die
ManyIterables
Klasse aus demselben Paket:1 Dies ist aus einer Drittanbieter-Bibliothek, die ich geschrieben habe :
iteration_utilities
.quelle
Ich würde zip () verwenden, um einen lesbaren und einfachen Weg zu finden:
quelle