Forum: Offtopic Textdatei nach den häufigsten Worten durchsuchen


von Max (Gast)


Lesenswert?

Hallo,

ich habe eine Textdatei von ca 50Mb und will diese nun nach den 
häufigsten Worten durchsuchen.

Kennt ihr ein Programm oder eine Möglichkeit, wie ich dies machen 
könnte?
Ich habe ja schon an eine MySql Datenbank gedacht, aber ich weiß nicht 
wie ich die 50Mb importieren könnte

Gruß

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Nei nei da bauste Dir einfach nen aussoziatives Array aus den 
vorkommenden Worten auf und machst nen Inkrement, sowas is in 10 Minuten 
hinprogrammiert... danach sortierst das Array nach den Werten und gibst 
es aus, damit haste Deine Topliste.

von Max (Gast)


Lesenswert?

Hallo,

da müsste ich aber erst auf die Datei zugreifen können. Mit welcher 
Sprache würdest du denn deinen Vorschlag umsetzen?

von Karl H. (kbuchegg)


Lesenswert?

Mit C++


Als erster Ansatz
1
#include <iostream>
2
#include <map>
3
#include <string>
4
5
int main()
6
{
7
  std::map< std::string, long > Distri;
8
  std::string word;
9
10
  while( std::cin >> word )
11
    Distri[word]++;
12
13
  for( std::map< std::string, long >::iterator it = Distri.begin();
14
       it != Distri.end();
15
       it++ )
16
    std::cout << it->first << " " << it->second << std::endl;
17
18
  return EXIT_SUCCESS;
19
}

Wenn man diesem Programm seinen eigenen Quelltext vorwirft,
kommt sowas raus:
1
C:\Heinz\Entwicklung\Forum12\Debug>forum12 < ..\forum12.cpp
2
!= 1
3
" 2
4
#include 3
5
<< 4
6
<iostream> 1
7
<map> 1
8
<string> 1
9
= 1
10
> 1
11
>::iterator 1
12
>> 1
13
Distri.begin(); 1
14
Distri.end(); 1
15
Distri; 1
16
Distri[word]++; 1
17
EXIT_SUCCESS; 1
18
for( 1
19
int 1
20
it 2
21
it++ 1
22
it->first 1
23
it->second 1
24
long 2
25
main() 1
26
return 1
27
std::cin 1
28
std::cout 1
29
std::endl; 1
30
std::map< 2
31
std::string 1
32
std::string, 2
33
warning 1
34
while( 1
35
word 1
36
word; 1
37
{ 1
38
} 1
39
40
C:\Heinz\Entwicklung\Forum12\Debug>

Wie man sieht, müsste man an der 'Worterkennung' im Zusammenhang
mit Satzzeichen noch etwas arbeiten. Das Standardmässige 'ein
Wort läuft von einem Whitespace zum nächsten' ist vor echten
Prosatext nicht wirklich geeignet.

von Uhu U. (uhu)


Lesenswert?

// So gehts mit JavaScript:

var path = 'c:/datei.txt';

var Shell = new ActiveXObject("WScript.Shell");

var fso = new ActiveXObject("Scripting.FileSystemObject");


function RankCmp(w1, w2) {
   return w2 - w1;
}

var wordList = [];

var hF = fso.OpenTextFile(path);
while (!hF.AtEndOfStream) {
   var l = hF.ReadLine();
   var words = l.match(/[^ ]+/);
   for (var i in words) {
      if (typeof(wordList) == 'undefined') {
         wordList[words[i]] = 1;
      } else {
         wordList[words[i]]++;
      }
   }
}

wordRank = wordList.sort(RankCmp);

// wordRank enthält jetzt die Liste der Worte abfallend sortiert nach 
Häufigkeit.

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Hier ist noch eine Loesung in Perl:

#-------------------------------------------
#!/usr/bin/perl

use warnings;
use strict;

my %words;
while (<>) {
  foreach my $word (split /\s+/, $_) {
    if (defined $words{$word}) {
      $words{$word}++;
    } else {
      $words{$word} = 1;
    }
  }
}

foreach my $key (sort keys %words) {
  print $key.": ".$words{$key}."\n";
}

#---------------------------------------------

michael@quark:/stuff/test/perl> ./count-words.pl < count-words.pl
: 8
".$words{$key}."\n";: 1
#!/usr/bin/perl: 1
$_): 1
$key: 1
$key.":: 1
$word: 1
$words{$word}: 1
$words{$word}): 1
$words{$word}++;: 1
%words): 1
%words;: 1
(<>): 1
(defined: 1
(sort: 1
(split: 1
/\s+/,: 1
1;: 1
=: 1
else: 1
foreach: 2
if: 1
keys: 1
my: 3
print: 1
strict;: 1
use: 2
warnings;: 1
while: 1
{: 5
}: 5


Selbige Verbesserung mit Satzzeichen usw... aber vom Prinzip her gleich.

von yalu (Gast)


Lesenswert?

Der Vollständigkeit halber noch eine Python-Variante:
1
#!/usr/bin/python
2
from sys import argv
3
from string import maketrans
4
5
count = {}
6
punct = "!\"$%&/()[]{}=?\\@*+~#'<>|,.-;:_"
7
trans = maketrans(punct, len(punct) * " ")
8
for line in file(argv[1]):
9
  line = line.translate(trans).lower()
10
  for word in line.split():
11
    try:
12
      count[word] += 1
13
    except KeyError:
14
      count[word] = 1
15
items = count.items()
16
items.sort(key=lambda x: x[1], reverse=True)
17
for item in items:
18
  print "%-20s %6d" % item

Auf den Wikipedia-Artikel über Python losgelassen liefert es folgendes:
1
python                   97
2
die                      66
3
und                      56
4
der                      53
5
in                       53
6
ist                      31
7
von                      30
8
eine                     27
9
1                        25
10
für                      25
11
das                      23
12
auch                     21
13
werden                   20
14
3                        19
15
x                        18
16
als                      17
17
zu                       17
18
wie                      17
19
2                        17
20
bei                      17

50 MB gehen auf einem Pentium 4 mit 3,2 GHz in etwa 20 Sekunden durch.

von yalu (Gast)


Lesenswert?

Habe bei der Beispielsausgabe am Ende das "..." vergessen, die Ausgabe 
ist natürlich gekürzt.

von Max (Gast)


Lesenswert?

Danke für eure Antworten.

Jetzt muss ich den Quellcode nur noch compilieren bzw erst mal ein 
Compiler finden^^

von Max (Gast)


Lesenswert?

Hallo yalu,

ich habe mir mal python heruntergeladen. Nun habe ich ein Fenster 
"Python Shell" deinen Code habe ich nun da reinkopiert. Wie kann ich das 
jetzt starten?

von Max (Gast)


Lesenswert?

Ich habe es offenbar in das falsche Fenster kopiert. Nun habe ich es 
nochmal versucht und Python Shell zeigt mir nun
1
 
2
Traceback (most recent call last):
3
  File "C:/Python25/test", line 8, in <module>
4
    for line in file(argv[1]):
5
IndexError: list index out of range

von yalu (Gast)


Lesenswert?

> Hallo yalu,
>
> ich habe mir mal python heruntergeladen.

Danke für's Vertrauen ;-)

Das Programm ist für den Aufruf aus der Kommandozeile vorgesehen. Ich
nehme an, du arbeitest mit Windows? Wenn ja:

1. Kopier den Programmtext in einen Texteditor (Notepad oder was auch
   immer).

2. Speichere die Datei unter einem lustigen Namen, z.B. count.py.

3. Öffne ein DOS-Fenster.

4. Starte den Python-Interpreter mit dem Programm count.py und übergib
   als Argument den Namen der zu analysierenden Datei:

     python count.py langertext.txt

5. Bewundere das Ergebnis :)

Sollte das Kommando "python" nicht gefunden werden, musst du entweder
den vollständigen Pfad von python.exe angeben, oder das Verzeichnis,
in dem sich python.exe befindet, der Umgebungsvariable PATH
hinzufügen.

Das Ergebnis kann, wie üblich, durch Ausgabeumleitung in eine Datei
gespeichert werden:

  python count.py langertext.txt >ergebnis.txt

Vielleicht fängst du erst einmal mit kleineren Textdateien an, bis
alles richtig funktioniert ;-)

> Traceback (most recent call last):
>   File "C:/Python25/test", line 8, in <module>
>     for line in file(argv[1]):
> IndexError: list index out of range

Das Programm ist für Profis und deswegen absichtlich nicht tolerant
gegenüber Fehlbedienungen ;-)

Der Fehler erscheint, wenn man beim Start den Textdateinamen als
Argument weglässt. Starte das Programm wie oben beschrieben, dann
sollte es gehen.

von Max (Gast)


Lesenswert?

Vielen Dank für die Erklärung. Ich werde es gleich mal ausprobieren

Ich habe nur mal ein bischen VB und php^^ programmiert. Ich habe da eher 
wenig Ahnung.

von Max (Gast)


Lesenswert?

Ich habe es mal probiert
Das ist ja genial!! Ich muss mir das mal genauer ansehen, wie das 
funktioniert(;

von Tim (Gast)


Lesenswert?

Nur der vollständig halt halber noch eine Variante mit den mit den GNU 
tools (Sollte an jedem Linux Prompt funktionieren):

1
cat 50mb_file | sed -r "s/[ ,.]/\n/g" | sort | uniq -c | sort -n -r >stat.txt

ok, den regex für die Worterkennung kann man noch tunen...

von yalu (Gast)


Lesenswert?

> Ich muss mir das mal genauer ansehen, wie das funktioniert(;

Python ist eigentlich eine sehr leicht zu erlernende Sprache.
Allerdings ist das obige Programm vielleicht nicht das, was man sich
gleich als Erstes anschauen sollte, weil es trotz der Kürze schon
relativ viele Features der Sprache nutzt.

Falls du dich mit der Sprache etwas mehr auseinandersetzen möchtest,
ist das Tutorial sicher ein guter Startpunkt:

  http://docs.python.org/tut/tut.html

(Die ersten zwei Kapitel kannst du schnell überfliegen, spannend wird
es ab Kapitel 3.)

Falls du irgendwelche Fragen hast, gerne. Ich kann auch ein paar
Kommentare zu dem Programm schreiben. Aber nicht sofort, denn ich muss
jetzt auf Achse und weiß noch nicht genau, wann ich wieder im Netz
bin.

@Tim:
Das ist natürlich die ubercoole Variante, für die gar nichts zu
programmieren ist. Mir war gar nicht bewusst, dass uniq auch zählen
kann -> wieder was gelernt :)

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Ausser der C++-Variante wird nix compiliert ;) Perl und Co sind alles 
Sprachen, die unter Windows, Mac, Linux und einigen mehr Plattformen 
verfuegbar sind.

von Max (Gast)


Lesenswert?

Ja OK.^^
Aber bei den anderen brauche ich auch ein Programm(Interpreter oder so), 
dass das Skript abarbeitet

von Uhu U. (uhu)


Lesenswert?

Michael G. wrote:
> Ausser der C++-Variante wird nix compiliert ;) Perl und Co sind alles
> Sprachen, die unter Windows, Mac, Linux und einigen mehr Plattformen
> verfuegbar sind.

JavaScript ist bei Windows sogar standardmäßig dabei...

von Uhu U. (uhu)


Lesenswert?

Hier nochmal eine leicht überarbeitete Version:

// So gehts mit JavaScript:

var path = 'c:/datei.txt';

var Shell = new ActiveXObject("WScript.Shell");

var fso = new ActiveXObject("Scripting.FileSystemObject");

var wordList = [];

var hF = fso.OpenTextFile(path);
while (!hF.AtEndOfStream) {
   var l = hF.ReadLine();
   l = l.replace(/[.,;:!?]/g, '');   // Satzzeichen wegschmeißen
   var words = l.match(/[^ ]+/i);    // ignore case
   for (var i = 1; i < words.length; i++) {
      if (typeof(wordList) == 'undefined') {
         wordList[words[i]] = 1;
      } else {
         wordList[words[i]]++;
      }
   }
}

wordRank = wordList.sort();
for (i in wordRank) { // Wortliste mit Häufigkeit ausgeben
   WScript.StdOut.WriteLine(i + ' : ' + wordRank[i]);
}

von Max (Gast)


Lesenswert?

Jetzt muss ich mal ganz blöd fragen (;  wie starte ich den das 
JavaScript ?

von Uhu U. (uhu)


Angehängte Dateien:

Lesenswert?

Max wrote:
> Jetzt muss ich mal ganz blöd fragen (;  wie starte ich den das
> JavaScript ?

Nimm die angehängte Datei - mittlerweile nochmal korrigiert und getestet 
:-) -, ändere den Dateinamen (path = ...). [Achtung: wenn du \ im Pfad 
hast, dann muß der entweder verdoppelt - wie in C - oder durch / ersetzt 
werden.]

Dann: öffne eine Dos-Box und zieh einfach das Skript hinein.
Dann return und es läuft.

von Uhu U. (uhu)


Angehängte Dateien:

Lesenswert?

Diese Version sortiert die Liste ordentlich - für Assoziativ-Arrays 
funktioniert sort nicht...

von Uhu U. (uhu)


Lesenswert?

Zeile 14 muß lauten:

    for (var i = 0; words && i < words.length; i++) {

sonst wird das erste Wort in einer Zeile nicht gezählt.

Wenn man Visual Studio, oder Microsoft Script Editor (aus Frontpage 
2003) hat, kann man js-Programme sehr komfortabel debuggen:

- Man erzeugt einen Shortcut auf die Datei, dann
- ändert man die Aufrufzeile im Shortcut auf:

      cscript //x test.js

- dann startet man den Shortcut.

Eine einigermaßen brauchbare Dokumentation findet man hier: 
http://msdn2.microsoft.com/en-us/library/72bd815a.aspx

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.