2016-07-10 11 views
1

ich einen Code haben, der etwas tut, wie:Python: Split eine durch Kommata getrennte Zeichenfolge direkt in einen Satz

if string in comma_delimited_string.split(','): 
    return True 

This website sagt, dass die Mitgliedschaft Tests mit Sätzen und dicts viel schneller ist, dass mit Listen oder Tupel. Ich weiß, set(comma_delimited_string.split(',')) würde Geschwindigkeit nicht verbessern, weil eine Liste noch erstellt wird, bevor es in ein Set konvertiert wird (oder zumindest schien es zu verlangsamen, wenn ich es zeitlich).

Ich frage mich dann, (meistens aus Neugier als echter Vorteil für meinen Code), gibt es eine Möglichkeit, den gleichen Effekt von comma_delimited_string.split(',') zu erreichen, sondern direkt ein Set, anstatt einer Liste, mit der Absicht zu beschleunigen die obige Operation?

Antwort

2

Nein, die str.split Operation gibt immer eine Liste zurück und versucht, diese in eine set umzuwandeln kostet Zeit. Auch Ihre eigenen handgemachten Schreiben split, die direkt ein Satz erzeugt wird langsamer sein, weil str.split ist implemente in C (der Quellcode sollte unter Objects/stringlib/split.h sein)

ist jedoch zu beachten, dass wenn Ihre string enthält kein Komma und Sie erwarten string nicht ein Teil der Elemente durch split, dann können Sie nur tun zurückgekehrt sein:

if string in comma_delimited_string: 

Wenn string enthält ein Komma, dann Test wird immer fehlschlagen (weil durch def Die Elemente von text.split(',') werden niemals einen enthalten.

Der Fall, in dem die obige Bedingung nicht ist, wenn Sie so etwas wie haben:

if "a" in "aaa,bb,c".split(',') 

, weil in diesem Fall "a" in ["aaa", "bb", "c"] ausfällt.

Alternativ können Sie einen regulären Ausdruck verwenden:

import re 
if re.search(r'(^{0},)|(,{0},)|(,{0}$)|(^{0}$)'.format(re.escape(string)), comma_delimited_string): 

aber ich weiß nicht, ob dies schneller sein würde, ist es wahrscheinlich auf Ihre Eingaben abhängt.

+0

@Bakuriu Danke für die Antwort - in meinem Fall betrachte ich Dokumentnummern, die ziemlich mehrdeutig sind (zB da können die Dokumente '' 10'' und '' 103'' sein), also eine reine 'Zeichenkette in Komma_limit_string' ist nicht ganz zutreffend. Also, ich denke, Sie sagen, der einzige Weg, um eine direkte Umwandlung von Komma-Trennzeichen in eine Menge so schnell wie '.split 'würde es in C schreiben zu machen? .... nicht so bald. – dieggsy

+0

@therockmandolinist Ja, das ist es, was ich sage. Sie müssten den Code für 'split' kopieren und einfügen und stattdessen ein Set anstelle einer Liste verwenden. Es ist ziemlich mühsam, also würde ich das nur tun, wenn es entscheidend ist, dass diese Überprüfung so schnell wie möglich sein muss ... – Bakuriu

3

Sie ignorieren die Tatsache, dass, um alles in ein Set zu konvertieren, müssen Sie es iterieren. Und diese Iteration ist genau so, wie Sie es bereits tun, um die ursprüngliche Liste zu durchsuchen. Es kann also keinen Vorteil haben, nur Overhead.

Die Suche nach einem Set ist effizienter, wenn Sie es mehrmals ausführen, da Sie dadurch die Kosten der Konvertierung amortisieren können. Aber die Umwandlung selbst wird immer ein linearer Scan sein; Es gibt keine Möglichkeit das zu vermeiden.

+0

Nun, meine Argumentation war, dass zum Beispiel für eine bereits erstellte Liste und mit gleichen Mitgliedern gesetzt ' 1 ',' 2 ',' 3 ', ...' 1000000 ', die Überprüfung von' '1000000' in my_set' war eine gute Menge schneller als '' 1000000 'in my_list', zumindest wenn ich es zeitlich gemessen habe. Wenn es eine Methode gäbe, eine kommagetrennte Zeichenkette direkt in eine Menge umzuwandeln, die die gleiche Zeit wie die '.split' Methode benötigen würde, könnte der tatsächliche Mitgliedschafts-Test beschleunigt werden. – dieggsy

+0

Gedanken: Ich denke, die einzige Möglichkeit, die kommagetrennte Zeichenfolge in eine Menge so schnell wie '.split' zu konvertieren, könnte sein, eine benutzerdefinierte Implementierung in C zu schreiben, was, wie Sie sagten, Overhead ist. – dieggsy

1

Während ein Mitgliedschaftstest für eine vorhandene Menge möglicherweise schneller ist (O (1)) als für eine Liste (O (n)), müssen Sie die Menge dennoch aus der Zeichenfolge erstellen, die O ist (n). Sie können also nichts gegen die zeitliche Komplexität unternehmen.

(',%s,' % string) in (',%s,' % comma_delimited_string) 

Sie nicht diese verwenden, wenn Sie haben einen wirklich guten Grund zu: obwohl nur durch Abtasten der Zeichenfolge anstelle des Konstruierens Zwischendatenstrukturen

Sie können den Test mit einem konstanten Faktor beschleunigen.

+0

Ja, ich meinte, die Saite so lange in einen Satz zu verwandeln, wie die '.split'-Methode daraus eine Liste macht, die dann den Mitgliedschaftstest beschleunigen würde. Interessante Antwort, dies funktioniert auf die gleiche Weise wie die Suche nach einer Mitgliedschaft in einer Liste für eine gegebene Zeichenfolge. Warum sagst du, dass es nicht benutzt werden sollte? – dieggsy

+0

Schön, bei meinen Testdaten brauchte es nur 500ns statt 2,5μs für 'Split'. Aber aus einer Lesbarkeits-Perspektive, und wenn Geschwindigkeit nicht von äußerster Wichtigkeit ist, denke ich, sollte man mit "Split" gehen. –

+0

@tobias_k Ich verstehe Ihren Standpunkt, und das ist sehr sinnvoll für sehr komplexe Optimierungen. Ich denke, es könnte nur eine Frage der Präferenz sein, aber ich denke, im Allgemeinen würde ich es vorziehen, die Leistung gegenüber der Lesbarkeit zu optimieren, besonders wenn (wie in diesem Fall) das Opfer nicht zu groß ist. Ich bin erst vor Kurzem _really_ in die Programmierung gekommen, also könnt ihr mich vielleicht anders überzeugen. – dieggsy

Verwandte Themen