Anzahl von Wörtern in String zählen
Ich weiss, man sollte nicht immer fertigen Lösungen liefern...
Folgendes habe ich mal über eine 40GB Passwortliste laufen lassen um zu sehen, wieviel Wörter da drin sind..
EDIT:
Oder falls die einzelnen Wörter gezählt werden sollen:
Folgendes habe ich mal über eine 40GB Passwortliste laufen lassen um zu sehen, wieviel Wörter da drin sind..
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
fileName = "Dein String, Deine Textdatei"
num_lines = 0
num_words = 0
num_chars = 0
with open(fileName, 'r') as f:
for line in f:
words = line.split()
num_lines += 1
num_words += len(words)
num_chars += len(line)
print "Anzahl Zeilen: ", num_lines
print "Anzahl Wörter: ", num_words
print "Anzahl Buchstaben: ", num_chars
Oder falls die einzelnen Wörter gezählt werden sollen:
Code: Alles auswählen
from collections import Counter
with open("test.txt") as f:
counts = Counter(f.read().split())
print counts
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ich biete noch das:
Könnte schneller sein, als die Variante mit ``split``, da keine Liste erstellt werden muss. Aber lesbarer ist natürlich die anderen. Müsste man glatt mal testen.
Code: Alles auswählen
import re
s = " Hallo Welt, das ist ein Test! "
sum(1 for space in re.finditer(r"[^\s]+", s))
> 6
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@Hyperion: die inverse Menge zu »\s« ist »\S«. Und die Variante über reguläre Ausdrücke ist rund 6mal langsamer.
Code: Alles auswählen
re.sub(r'\w+', 'x', text).count('x')
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ah sieh an... hätte ich nicht gedacht. (Ich nehme an Du meintest meine Variante?) Wie sieht es denn mit Deiner aus?Sirius3 hat geschrieben:Und die Variante über reguläre Ausdrücke ist rund 6mal langsamer.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Ich hab das mal mit einer Logdatei (2,1MB) mit jeweils 100 durchgängen (ohne Interpreterstart oder Imports) getestet und die Zeit mit dem Tool "time" gemessen:
Dauer: 58s
Dauer: 61s
Dauer ohne Textausgabe: 1m 7s
Dauer mit Textausgabe: 2m 22s
Dauer: 11s
Daraus schließe ich 3 Dinge:
a) Immer zuerst das Einfachste probieren (KISS)
b) Keinesfalls verfrüht optimieren (oder einfach gar nicht, funktioniert auch so wunderbar)
c) Ich sollte mir andere Hobbies suchen
mfg
Code: Alles auswählen
import re
for x in range(0,100):
with open ('test.txt', 'r') as f:
print(sum(1 for space in re.finditer(r"[\S]+", f.read())))
Code: Alles auswählen
import re
for x in range(0,100):
with open ('test.txt', 'r') as f:
print(sum(1 for space in re.finditer(r"[^\s]+", f.read())))
Code: Alles auswählen
from collections import Counter
for x in range(0,100):
with open('test.txt') as f:
counts = Counter(f.read().split())
print(counts)
Dauer mit Textausgabe: 2m 22s
Code: Alles auswählen
for x in range(0,100):
with open('test.txt', 'r') as f:
print(len(f.read().split()))
Daraus schließe ich 3 Dinge:
a) Immer zuerst das Einfachste probieren (KISS)
b) Keinesfalls verfrüht optimieren (oder einfach gar nicht, funktioniert auch so wunderbar)
c) Ich sollte mir andere Hobbies suchen
mfg
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Wobei hier alle Loesungen ein potentielles Problem mit richtig grossen Dateien haben. Vor allem 4, da hier zeitweise das doppelte der Dateigroesse an Speicher benoetigt wird.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Ich denke alle 4 von mir getesteten Implementierungen haben Probleme beim Speicherbedarf, andreseits wer hat schon Textdateien > 50MB? Das dürfte wohl eher die Ausnahme darstellen.cofi hat geschrieben:Wobei hier alle Loesungen ein potentielles Problem mit richtig grossen Dateien haben. Vor allem 4, da hier zeitweise das doppelte der Dateigroesse an Speicher benoetigt wird.
mfg
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Aber nur das 4. belegt zeitweise das doppelte an Speicherplatz. Wer so grosse Textdateien hat? Jemand der Log-Dateien hat, und das ist nur einer von vielen Faellen ..
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Dann halt noch die speicherschonende Variante:
mit maximal einem Zeichen im Speicher
Code: Alles auswählen
with open('test.txt') as f:
print(reduce(
lambda (s,b),c: (s+(b and b!=c.isspace()), c.isspace()),
iter(lambda: f.read(1), ''), (0,1))[0])
Log-Dateien werden für gewöhnlich nicht größer als 10MB (Erfahrungswert), selbst auf meinen Server finde ich dank logrotate keine einzige Logdatei > 3MB.cofi hat geschrieben:Aber nur das 4. belegt zeitweise das doppelte an Speicherplatz. Wer so grosse Textdateien hat? Jemand der Log-Dateien hat, und das ist nur einer von vielen Faellen ..
Ein Buch mit etwa 700 Seiten dürfte in reiner Textform und UTF-8 Codierung nicht größer als 2MB sein.
Meine kleine Liste mit Passwörtern hat knapp 30000 Einträge und selbst die belegt nicht mehr als 300kB.
Ich will nicht bestreiten, dass die 4. Lösung zeitweise den doppelten Speicher belegt. Allerdings dürften nur die wenigsten Leute, die Wörter in einem Textdokument zählen wollen, Dateien > 50MB verwenden.
Was mir noch in den Sinn kommen würde sind Hashtables, die man allerdings aus verschiedenen Gründen wohl besser in eine Datenbank packt.
mfg
@JohnDoe: Das ist wohl ein persönlicher Erfahrungswert von Dir. Ich kenne grössere Logdateien. Und auch Textdateien mit Messungen die deutlich grösser sind. Auf der anderen Seite kenne ich auch Rechner die nicht mehrere GiB RAM haben.
JohnDoe hat geschrieben: Meine kleine Liste mit Passwörtern hat knapp 30000 Einträge und selbst die belegt nicht mehr als 300kB.
mfg
Meine PW Liste mit 20GB
Code: Alles auswählen
Anzahl Zeilen: 4'103'549'346
Anzahl Wörter: 4'103'549'346
Anzahl Buchstaben: 24'541'533'232
Code: Alles auswählen
Anzahl Zeilen: 3917193
Anzahl Wörter: 4101726
Anzahl Buchstaben: 43391014
Es geht mir nicht darum ob es Logdateien gibt die größer sind als 50MB und es geht mir auch nicht darum, ob es Rechner gibt die weniger als 1GB RAM haben. Wenn man, wie @lackschuh, eine Passwortliste mit 20GB rumschleppt, dann lohnt es sich das Programm so zu erweitern, dass es mit der Datenmenge klarkommt. Ansonsten: Optimierungen immer erst dann anwenden, wenn es nötig ist.BlackJack hat geschrieben:Ich kenne grössere Logdateien. Und auch Textdateien mit Messungen die deutlich grösser sind. Auf der anderen Seite kenne ich auch Rechner die nicht mehrere GiB RAM haben.
Mehr wollte ich nicht ausdrücken.
mfg
Hier mal eine Variante, die häppchenweise lesen kann:
Code: Alles auswählen
def count_words(stream, chunk_size=1024*1024):
num_words = 0
saw_nonspace = False
chunk_reader = iter(lambda: stream.read(chunk_size), '')
for chunk in chunk_reader:
num_chunk_words = len(chunk.split())
if saw_nonspace and not chunk[0].isspace():
num_chunk_words -= 1
num_words += num_chunk_words
saw_nonspace = not chunk[-1].isspace()
return num_words
def test():
from StringIO import StringIO
s = StringIO(" as s s s ")
print count_words(s, 2)
if __name__ == '__main__':
test()