mikrocontroller.net

Forum: Offtopic Textdatei nach den häufigsten Worten durchsuchen


Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit C++


Als erster Ansatz
#include <iostream>
#include <map>
#include <string>

int main()
{
  std::map< std::string, long > Distri;
  std::string word;

  while( std::cin >> word )
    Distri[word]++;

  for( std::map< std::string, long >::iterator it = Distri.begin();
       it != Distri.end();
       it++ )
    std::cout << it->first << " " << it->second << std::endl;

  return EXIT_SUCCESS;
}

Wenn man diesem Programm seinen eigenen Quelltext vorwirft,
kommt sowas raus:
C:\Heinz\Entwicklung\Forum12\Debug>forum12 < ..\forum12.cpp
!= 1
" 2
#include 3
<< 4
<iostream> 1
<map> 1
<string> 1
= 1
> 1
>::iterator 1
>> 1
Distri.begin(); 1
Distri.end(); 1
Distri; 1
Distri[word]++; 1
EXIT_SUCCESS; 1
for( 1
int 1
it 2
it++ 1
it->first 1
it->second 1
long 2
main() 1
return 1
std::cin 1
std::cout 1
std::endl; 1
std::map< 2
std::string 1
std::string, 2
warning 1
while( 1
word 1
word; 1
{ 1
} 1

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.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Vollständigkeit halber noch eine Python-Variante:
#!/usr/bin/python
from sys import argv
from string import maketrans

count = {}
punct = "!\"$%&/()[]{}=?\\@*+~#'<>|,.-;:_"
trans = maketrans(punct, len(punct) * " ")
for line in file(argv[1]):
  line = line.translate(trans).lower()
  for word in line.split():
    try:
      count[word] += 1
    except KeyError:
      count[word] = 1
items = count.items()
items.sort(key=lambda x: x[1], reverse=True)
for item in items:
  print "%-20s %6d" % item

Auf den Wikipedia-Artikel über Python losgelassen liefert es folgendes:
python                   97
die                      66
und                      56
der                      53
in                       53
ist                      31
von                      30
eine                     27
1                        25
für                      25
das                      23
auch                     21
werden                   20
3                        19
x                        18
als                      17
zu                       17
wie                      17
2                        17
bei                      17

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

Autor: yalu (Gast)
Datum:

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

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten.

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

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es offenbar in das falsche Fenster kopiert. Nun habe ich es 
nochmal versucht und Python Shell zeigt mir nun
 
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

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Max (Gast)
Datum:

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

Autor: Tim (Gast)
Datum:

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

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...

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Max (Gast)
Datum:

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

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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]);
}

Autor: Max (Gast)
Datum:

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

Autor: Uhu Uhuhu (uhu)
Datum:
Angehängte Dateien:
  • test.js (720 Bytes, 27 Downloads)

Bewertung
0 lesenswert
nicht 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.

Autor: Uhu Uhuhu (uhu)
Datum:
Angehängte Dateien:
  • test.js (910 Bytes, 40 Downloads)

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

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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, Yahoo oder Facebook? Keine Anmeldung erforderlich!
Mit Google-Account einloggen | Mit Yahoo-Account einloggen | Mit Facebook-Account einloggen
Noch kein Account? Hier anmelden.