Petra Steiner: tied hashes und MLDBM

Hallo miteinander,

ich habe mit Sprachmassendaten zu tun. Und weil die bald
Speicherprobleme verursachen werden, versuchte ich es
mit tie und nun läuft das Programm nicht mehr so, wie es soll:

#!/usr/local/bin/perl -w

$ = 1;

require 5.005;   # not sure if earlier works as well

use strict;
use DB_File;            # DB Unterstützung
use MLDBM qw(DB_File Storable);

etc.
tie (%hKotext, 'MLDBM', "Testfile", O_RDWRO_CREAT, 0, $DB_BTREE)
    or die "Fehler beim öffnen der DB: $!" ;

etc.
push(@{$hKotext{$sKotstring}}, join("+", @zwischenelemente));

etc.

Rauskamen (ohne tie) bisher solche Zeilen:

2417 ,#, 16 die 10 sagt+er      9 Abb.  8 ist   7 der   6 weiß  5 das   5 dort  4 das+heißt     4 nein  4 vor+allem     4 war   3 bitte
3 das+sich  etc.

(da wird jede Menge textuelles Material sortiert und gezählt)

nun sieht das stattdessen so aus:
0 ,#, 1

Es  schaut so aus, als würde auch mit MLDBM  die
Verarbeitung von Hashes, die als Werte Arrays haben,
nicht funktionieren. Ich bekomme auch entsprechende
Fehlermeldungen.

Anscheinend funktioniert:

push(@{$hKotext{$sKotstring}}, join("+", @zwischenelemente));

nicht. Wer weiss Rat?

(Übrigens bin ich neu hier und finde das Forum äußerst nützlich und nett!)

Gruß,

Petra

  1. Ich kann nicht gut genug Perl, um Deine Frage zu lösen, nur ein paar Anregungen:

    Mach doch mal ein paar einfachere Textzugriffe auf den Hash und schau hinein, ob dort das drin steht, was Du erwartest.

    Es  schaut so aus, als würde auch mit MLDBM  die
    Verarbeitung von Hashes, die als Werte Arrays haben,
    nicht funktionieren. Ich bekomme auch entsprechende
    Fehlermeldungen.

    Brauchst Du das unbedingt? Will sagen: Greifst Du direkt indizierend auf Komponenten der Arrays zu?

    Alternativ könntest Du das über eine Funktion einschalen, die einen Hash-Inhalt mit split dynamisch zerlegt und die gewünschte Komponente zurückliefert. (Dann enthielte der Hash selbst nur Strings mit via join() codierten Tabellenzeilen.)

    Anscheinend funktioniert:
    push(@{$hKotext{$sKotstring}}, join("+", @zwischenelemente));
    nicht. Wer weiss Rat?

    Ich an dieser Stelle leider nicht - sorry.
    So wie ich "perldsc.html" über komplexere Datenstrukturen verstanden habe, würden die wohl einen Hash of Lists verwenden - ein Hash of Arrays ist dort nicht explizit beschrieben.

    1. Hallo Michael,
      danke für Deine schnelle Antwort.  
      Hier erstmal ein Lösungsansatz, wobei ich noch nicht sagen kann, dass er auch funktioniert, da das Programm noch läuft ...  Mit MLDBM tie kann man zwar durchaus Hashes von Arrays bearbeiten, aber eben doch nicht genauso wie ohne tie.
      Die Änderungen sind dieser Art:

      $tmp = $hKotext{$sKotstring};
           push(@{$tmp}, join("+", @zwischenelemente));
           $hKotext{$sKotstring} =$tmp;

      So wie ich das verstanden habe: Der Wert, auf den die
      Referenz von $hKotext{$sKotstring} verweist, wird $tmp zugewiesen.

      Wie geschrieben, ich muss erst schauen, ob es so geht, aber die Lösung geht in diese Richtung. Weil ich am Wochenende wohl nicht da bin, wollte ich Dir zumindest schon mal dies als Rückmeldung geben.

      Brauchst Du das unbedingt? Will sagen: Greifst Du direkt indizierend auf Komponenten der Arrays zu?

      Ähhh. Was ist "direkt indizierend"? - Ich zähle und sortiere jedenfalls die Elemente, die im Array stehen. Und diese Elemente sind außerdem noch komplex, d.h. es kann sich um Elemente mit einem oder mehreren Unterelementen (=Wörtern) handeln. Das sieht dann so aus:
      vor+allem zum+Beispiel Wort Michael Michael+Schröpf Schröpf etc.

      Alternativ könntest Du das über eine Funktion einschalen, die einen Hash-Inhalt mit split dynamisch zerlegt und die gewünschte Komponente zurückliefert. (Dann enthielte der Hash selbst nur Strings mit via join() codierten Tabellenzeilen.)

      Kann ich die dann noch sortieren? Um eine Liste komme ich doch wohl nicht rum?

      Ich an dieser Stelle leider nicht - sorry.
      So wie ich "perldsc.html" über komplexere Datenstrukturen verstanden habe, würden die wohl einen Hash of Lists verwenden - ein Hash of Arrays ist dort nicht explizit beschrieben.

      Ich dachte immer, eine Liste sei identisch mit einem Array in Perl. Sorry, ich bin noch ziemliche Anfängerin.
      Das Problem ist aber vor allem, dass das Programm was ganz anderes macht, sobald Du das hash tiest.

      Bald mehr von

      Petra

      1. Brauchst Du das unbedingt? Will sagen: Greifst Du direkt indizierend auf Komponenten der Arrays zu?
        Ähhh. Was ist "direkt indizierend"? - Ich zähle und sortiere jedenfalls die Elemente, die im Array stehen. Und diese Elemente sind außerdem noch komplex

        Ich meinte: Bist Du *nach* der Belegung des Hashs noch darauf angewiesen, einen optimal schnellen Zugriff auf jedes einzelne Array-Element zu haben?

        Oder reicht es aus, Array als Strings zu halten, bei Bedarf zu "entpacken" (und sortieren und was auch immer) und dann wieder zu "packen"?
        (Im Klartext: Mehr CPU-Zeit, aber einfachere Speicherstruktur.)

        Kann ich die dann noch sortieren? Um eine Liste komme ich doch wohl nicht rum?

        Aber ggf. nur *eine* (temporäre) Liste, nicht einen Hash voll von diesen Strukturen.
        (Je nachdem, wie gleichzeitig Du im gesamten Hash änderst.)

        einem Array in Perl. Sorry, ich bin noch ziemliche Anfängerin.

        Ich auch, was komplexe Datenstrukturen angeht.
        Ich denke halt in "Pascal plus Hashes" und schreibe es so gut es geht in Perl hin ... ;-)

        1. Hallo Michael,
          es hat so funktioniert, wie ich dachte.

          Oder reicht es aus, Array als Strings zu halten, bei Bedarf zu "entpacken" (und sortieren und was auch immer) und dann wieder zu "packen"?

          Theoretisch ja, praktisch nein, da Stringfunktionen den Zeitbedarf ganz enorm aufblähen. Besonders wenn Du irgendwann mal 100 Mio Token verarbeiten möchtest ... (momentan sind es noch lediglich 500.000).

          Aber ggf. nur *eine* (temporäre) Liste, nicht einen Hash voll von diesen Strukturen.
          (Je nachdem, wie gleichzeitig Du im gesamten Hash änderst.)

          Neinnein, ich sortiere direkt vor der zeilenweisen Ausgabe und für die Sortierung der Gesamthäufigkeiten habe ich einen Extra-Hash angelegt, der nur die Keys + Häufigkeiten als Werte hat.

          Ich denke halt in "Pascal plus Hashes" und schreibe es so gut es geht in Perl hin ... ;-)

          Ich glaube, ich bin in diesem Forum auch eher eine Ausnahme, wo ich Perl gar nicht für CGI-Programme verwende. Aber vielleicht wird es für die anderen ja doch mal interessant. Zu tied hashes gabs bisher noch nie Fragen ...

          Viele Grüße, schönes Wochenende!

          Petra

          1. Theoretisch ja, praktisch nein, da Stringfunktionen den Zeitbedarf ganz enorm aufblähen. Besonders wenn Du irgendwann mal 100 Mio Token verarbeiten möchtest ... (momentan sind es noch lediglich 500.000).

            Hm, dann wird CPU-Zeit eine enge Ressource - und eine Interpretersprache wie Perl möglicherweise nur die zweitbeste Lösung sein.

            Ich glaube, ich bin in diesem Forum auch eher eine Ausnahme, wo ich Perl gar nicht für CGI-Programme verwende. Aber vielleicht wird es für die anderen ja doch mal interessant. Zu tied hashes gabs bisher noch nie Fragen ...

            Seitdem ich CGI-Programme schreibe, nehme ich oft auch Perl für kleinere lokale Aufgaben.

            In Deinem Falle würde ich aber wenigstens mal kurz darüber nachdenken, ob C++ mit geeigneten Klassenbibliotheken nicht die bessere Alternative sein könnte.

            1. In Deinem Falle würde ich aber wenigstens mal kurz darüber nachdenken, ob C++ mit geeigneten Klassenbibliotheken nicht die bessere Alternative sein könnte.

              Hab ich schon vor einigen Wochen und Monaten getan. - Perl ist nun mal für Textverarbeitung sehr gut geeignet und in der Linguistik sehr beliebt, d.h. viele meiner KollegInnen können den relativ durchschaubaren Code relativ schnell verstehen.  Nicht ohne Grund ist Larry Wall von Hause aus Linguist! (Wen es interessiert: im Vorwort stehts:
              http://www.ora.de/german/prog/perlprog/wall.html).

              Außerdem hier noch ein Perlkurs nicht nur für Linguistikstudis:

              http://www.georgetown.edu/cball/perl/

              Schönes Wochenende auch!

              Petra