2010-12-07 14 views
4

Grundsätzlich möchte ich ein Zeichen in einer Zeichenfolge nacheinander entfernen, wenn es mehrfach vorkommt.Entfernen eines Zeichens in einer Zeichenfolge nacheinander

Für zB: - wenn ich ein Wort abaccea und das Zeichen 'a' habe, dann sollte die Ausgabe der Funktion baccea, abacce, abccea sein.

Ich lese, dass ich maketrans für eine und leere Zeichenfolge machen kann, aber es ersetzt jedes a in der Zeichenfolge.

Gibt es eine effiziente Möglichkeit, dies zu tun außer noting alle Positionen in einer Liste und dann ersetzen und generieren die Wörter?

Antwort

5

Hier ist ein schneller Weg, es zu tun:

In [6]: s = "abaccea" 
In [9]: [s[:key] + s[key+1:] for key,val in enumerate(s) if val == "a"] 
Out[10]: ['baccea', 'abccea', 'abacce'] 

Es ist der Vorteil in der Lage, Verwandeln Sie dies in einen Generator, indem Sie eckige Klammern durch runde ersetzen.

+0

Ich denke, du willst 's [Taste + 1:]' – Triptych

+0

@Triptynch das ist, was ich geschrieben habe. –

1

Ich würde sagen, dass Ihr Ansatz gut klingt - es ist ein ziemlich effizienter Weg, um es zu tun, und es wird dem Leser klar sein, was Sie tun.

Eine etwas weniger elegante aber möglicherweise schnellere Alternative ist der start Parameter der find Funktion.

i = 0 
while True: 
    j = word.find('a', i) 
    if j == -1: 
     break 
    print word[:j] + word[j+1:] 
    i = j + 1 

Die Suchfunktion ist wahrscheinlich in C hoch optimiert werden, so dass dies möglicherweise in der Zeichenfolge selbst in Python eine Leistungsverbesserung im Vergleich zu Iterieren über die Zeichen geben. Ob Sie das tun möchten, hängt jedoch davon ab, ob Sie nach Effizienz oder Eleganz suchen. Ich würde empfehlen, zuerst den einfachen und klaren Ansatz zu wählen und ihn nur dann zu optimieren, wenn das Performance-Profiling zeigt, dass Effizienz ein wichtiges Thema ist.

Hier sind einige Performance-Messungen zeigen, dass der Code find mit schneller laufen kann:

 
>>> method1='[s[:key] + s[key+1:] for key,val in enumerate(s) if val == "a"]' 
>>> method2=''' 
result=[] 
i = 0 
while True: 
    j = s.find('a', i) 
    if j == -1: 
     break 
    result.append(s[:j] + s[j+1:]) 
    i = j + 1 
''' 

>>> timeit.timeit(method1, init, number=100000) 
2.5391986271997666 
>>> timeit.timeit(method2, init, number=100000) 
1.1471052885212885 
+0

Und warum kein Verständnis optimiert werden würde? (Ich frage nur, weil ich nicht weiß, ** nicht ** winseln) –

+0

@Gabi Purcaru: Theoretisch sollte der Generator Ausdruck in einer idealen Welt schneller sein. Die Standard-Distribution von Python enthält jedoch keinen JIT-Compiler, was bedeutet, dass jeder Code, den Sie in Python schreiben, langsamer läuft als Aufrufe, die Sie an C-Code senden. Da jeder von Ihnen durchgeführte Zeichenvergleich zu einem Python-Aufruf führt, läuft dieser ziemlich langsam, während der Code für 'str.find' in C geschrieben ist und nicht unter dem gleichen Problem leidet. Wenn Sie eine Python-Implementierung verwenden, die einen JIT-Compiler enthält, würde ich erwarten, dass der Leistungsunterschied geringer ist. –

+0

@Gabi Purcaru: Ich habe meiner Antwort einige Leistungsmessungen hinzugefügt. –

-2

Wie wäre es damit?

>>> def replace_a(word): 
...  word = word[1:8] 
...  return word 
... 
>>> replace_a("abaccea") 
'baccea' 
>>> 
+0

Dies beantwortet die Frage überhaupt nicht, und es funktioniert nur an dem sehr spezifischen Beispiel des Ersetzens des ersten 'a' in 'abaccea'. – eldarerathis

+0

oh sorry ... –

3

Sie könnten das folgende Skript versuchen. Es bietet eine einfache Funktion, um zu tun, was Sie fragen. Die Verwendung von Listen-Comprehensions [x for x in y if something(x)] ist es wert, gelernt zu werden.

#!/usr/bin/python 

word = "abaccea" 
letter = "a" 

def single_remove(word, letter): 
    """Remove character c from text t one at a time 
    """ 
    indexes = [c for c in xrange(len(word)) if word[c] == letter] 
    return [word[:i] + word[i + 1:] for i in indexes] 

print single_remove(word, letter) 

kehrt ['baccea', 'abccea', 'abacce']

Prost

Verwandte Themen