Textdatei nach den häufigsten Worten durchsuchen

Gast #789877
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ß
#789930
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.
#789955
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.
Persönliche Seite #789973
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.
Gast #790038
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.
Gast #790872
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
Gast #790886
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.
Gast #790903
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...
Gast #790934
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 :)
#791095
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]);
}
#791128
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.
Angehängte Dateien:
#791197
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren