Alle doppelten Wörter aus einem Readlines Array entfernen, ohne eingebaute Funktionen zu verwenden

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
__blackjack__
User
Beiträge: 5997
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Samstag 3. August 2019, 01:44

Na wenn alle möglichen Funktionen erlaubt sind, dann würde ich das mit den ASCII-Buchstaben sein lassen und `isalpha()` auf Zeichenketten benutzen:

Code: Alles auswählen

def skip_nonletters(iterator):
    return dropwhile(lambda c: not c.isalpha(), iterator)


def next_word(iterator):
    iterator = skip_nonletters(iterator)
    letters = takewhile(lambda c: c.isalpha(), iterator)
    return ''.join(letters)
long long ago; /* in a galaxy far far away */
Benutzeravatar
__blackjack__
User
Beiträge: 5997
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Samstag 3. August 2019, 01:58

Alternative Lösung mit `itertools`:

Code: Alles auswählen

#!/usr/bin/env python3
from operator import itemgetter
from itertools import groupby


def get_words(text):
    groups = groupby(((c.isalpha(), c) for c in text), itemgetter(0))
    return [
        ''.join(map(itemgetter(1), group))
        for is_word, group in groups if is_word
    ]


def test():
    print(get_words('Hallo, na du wie gehts\n'))
    print(get_words('Hallo na\n'))
    print(get_words('na wie Wochenende\n'))


if __name__ == '__main__':
    test()
long long ago; /* in a galaxy far far away */
Benutzeravatar
snafu
User
Beiträge: 6073
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Samstag 3. August 2019, 08:35

Der Ansatz mit groupby() lässt sich noch etwas knackiger formulieren, wenn nur Strings erlaubt sind:

Code: Alles auswählen

from itertools import groupby

def get_words(text):
    return [''.join(letters) for is_word, letters
            in groupby(text, str.isalpha) if is_word]

def test():
    print(get_words('Hallo, na du wie gehts\n'))
    print(get_words('Hallo na\n'))
    print(get_words('na wie Wochenende\n'))


if __name__ == '__main__':
    test()
Benutzeravatar
snafu
User
Beiträge: 6073
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Samstag 3. August 2019, 08:50

Der reguläre Ausdruck ist übrigens trotzdem fast doppelt so schnell (Rechner ist schon etwas älter):

Code: Alles auswählen

In [3]: %paste
from itertools import groupby
import re

def get_words_groupby(text):
    return [''.join(letters) for is_word, letters
            in groupby(text, str.isalpha) if is_word]

def get_words_re(text):
    return re.findall('[a-zA-Z]+', text)

def test():
    lines = ['Hallo, na du wie gehts\n', 'Hallo na\n', 'na wie Wochenende\n']
    for line in lines:
        words = get_words_groupby(line)
        assert words == get_words_re(line)
        print(words)

if __name__ == '__main__':
    test()

## -- End pasted text --
['Hallo', 'na', 'du', 'wie', 'gehts']
['Hallo', 'na']
['na', 'wie', 'Wochenende']

In [4]: %timeit get_words_groupby('Hallo, na du wie gehts\n')
26.5 µs ± 1.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [5]: %timeit get_words_re('Hallo, na du wie gehts\n')
14 µs ± 409 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Antworten