2016-08-01 11 views
1

Neugierig zu finden, wenn Menschen viel schneller als meine Implementierung (mit reinem Python, oder was auch immer, aber nur für Sie) tun können.Entfernen Sie Zeichen in Bereichen von einer Zeichenfolge

sentence = "This is some example sentence where we remove parts" 
matches = [(5, 10), (13, 18), (22, 27), (38, 42)] 

Das Ziel ist, innerhalb dieser Bereiche zu entfernen. Z.B. Die Zeichen bei den Indizes (5, 6, 7, 8, 9) sollten im Rückgabewert für die Übereinstimmung (5, 10) weggelassen werden.

Meine Implementierung:

def remove_matches(sentence, matches): 
    new_s = '' 
    lbound = 0 
    for l, h in matches: 
     news += sentence[lbound:l] 
     lbound = h 
    new_s += sentence[matches[-1][1]:] 
    return new_s 

Ergebnis: 'This me le sce where weove parts'

Beachten Sie, dass die Spiele nie überlappen, können Sie nutzen diese Tatsache machen.

Eigentlich ist meine Hauptfrage einfach: Können wir es nicht irgendwie vektorisiert machen? Ich bin mir sicher, dass das numpig sein könnte, aber ich bezweifle, dass das in diesem Fall effizienter wäre.

Benchmarks:

PascalvKooten:   1000000 loops, best of 3: 1.34 µs per loop 
Ted Klein Bergman (1): 1000000 loops, best of 3: 1.59 µs per loop 
Ted Klein Bergman (2): 100000 loops, best of 3: 2.58 µs per loop 
Prune:     100000 loops, best of 3: 2.05 µs per loop 
njzk2:     100000 loops, best of 3: 3.19 µs per loop 
+0

Wenn Sie uns Ihre Benchmarks geben, könnten wir in der Lage sein, zu prüfen, ob wir etwas schneller haben. –

+0

@AkshatMahajan: dann genügt es, seinen Code zu nehmen und eine schnellere Maschine zu verwenden. –

+0

@YvesDaoust: Durch diese Logik können Sie auch überhaupt kein Profil erstellen. –

Antwort

0
shorthend =sentence[:matches[0][0]]+ "".join([sentence[matches[i-1][1]:matches[0][0] for i in range(1, len(matches)]) + sentence[matches[len(matches)]:] 

Da ich auf meinem Handy‘jetzt, ich kann nicht debuggen, aber es sollte funktionieren: D

+0

Das habe ich auch geschrieben. Es ist tatsächlich wie 10% langsamer als meine Lösung: D – PascalVKooten

+0

Hmm, kann nicht verstehen, warum. Wahrscheinlich ist es ein ineffizienter Teil, die Liste zu erstellen, nur um sie wieder in eine Zeichenkette umzuwandeln. –

+0

Ja, ich denke, weil es relativ eine kleine Saite ist. – PascalVKooten

0

Wenn Sie (null, 0) anhängen an die Front und (-1, null) an der Rückseite der Spiele

sentence = "This is some example sentence where we remove parts" 
matches = [(null, 0), 
      (5, 10), (13, 18), (22, 27), (38, 42), 
      (len(sentence), null)] 

können Sie dann einen Ausdruck auf

01 basierend verbinden schreiben

Ist das genug von einem Hinweis, um Sie entlang zu bewegen?

+1

Es ist ein bisschen langsamer, obwohl ich bezweifle es signifikant. Beachten Sie, dass (-1, ...) am Ende uns 1 Zeichen verlieren lässt. – PascalVKooten

+0

Richtig; Vielen Dank! Korrigieren Sie dies zu Satzlänge. – Prune

+0

können Sie einfach 'None' hinzufügen, da' a [0: None] 'äquivalent zu' a [0:] ' – njzk2

1

Dies könnte schneller sein. Es ist im Grunde Ihre Lösung, aber mit einer Liste anstelle von Strings. Da Listen veränderbar sind und nicht in jeder Schleife erstellt werden müssen, sollte sie um einiges schneller sein (vielleicht nicht für so wenige Übereinstimmungen).

sentence = "This is some example sentence where we remove parts" 
matches = [(5, 10), (13, 18), (22, 27), (38, 42)] 

def remove_matches(sentence, matches): 
    result = [] 
    i = 0 
    for x, y in matches: 
     result.append(sentence[i:x]) 
     i = y 
    result.append(sentence[i:]) 

    return "".join(result) 

könnte diese Methode schneller anders sein:

def remove_matches(sentence, matches): 
    return "".join(
     [sentence[0:matches[i][0]] if i == 0 else 
     sentence[matches[i - 1][1]:matches[i][0]] if i != len(matches) else 
     sentence[matches[i - 1][1]::] for i in range(len(matches) + 1) 
     ]) 
+0

ist. Es ist ein interessanter Punkt in den Listen. Ich kann den Effekt tatsächlich sehen, wenn er sich vergrößert. – PascalVKooten

0

Haben die Saiten eine schnelle Lösung, indem die Zeichen an Ort und Stelle, um zusammenhängenden Teil wandelbar sein, möglich gewesen wäre.

Eine optimale C-Lösung würde aus einigen memmov-Aufrufen bestehen.

0

Statt Zeichen zu entfernen, würde ich definieren, wie sie zu halten, die Manipulation zu erleichtern:

sentence = "This is some example sentence where we remove parts" 
matches = [(5, 10), (13, 18), (22, 27), (38, 42)] 
chain = (None,) + sum(matches,()) + (None,) 
# 
keep = ((m1, m2) for m1, m2 in zip(chain[::2], chain[1::2])) 
# list(keep) = [(None, 5), (10, 13), (18, 22), (27, 38), (42, None)] 
# or, keep = ((m1[1], m2[0]) for m1, m2 in zip([(None, None)] + matches, matches + [(None, None)])) 
return ''.join(sentence[x:y] for x, y in keep) 
+0

Es ist ziemlich langsam für diese kleinen Daten und fügt es zu den Benchmark-Ergebnissen hinzu. – PascalVKooten