Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Einträge in Listview / Stringlist vergleichen;Strings zählen (https://www.delphipraxis.net/129948-eintraege-listview-stringlist-vergleichen%3Bstrings-zaehlen.html)

frieder2008 28. Feb 2009 03:38


Einträge in Listview / Stringlist vergleichen;Strings zählen
 
Hallo zusammen,

es ist inzwischen sehr spät und ich hänge seit Stunden an einem Problem: Ich habe eine Stringlist mit einzelnen Wörtern (Tokens); diese Tokens möchte ich nun - sofern identisch - zählen und in ein Listview ausgeben (Token + Frequenz).

Leider schaffe ich es weder, im Listview ein Item suchen zu lassen, so dass ich bei einem Neueintrag dann einfach die Frequenz erhöhen könnte (+1), noch schaffe ich es, innerhalb der Ausgangs-Stringlist und in Schleifen die doppelten Tokens zu finden, zu löschen und zu zählen.

Folgendes (mit sicherlich inzwischen mehreren Fehlern, die ich auf Grund von Müdigkeit nicht mehr schnalle) habe ich gezimmert:

Wie ihr seht, hab ich sogar irgendwann aus Hilfslosigkeit mit Goto-Verweisungen zu arbeiten versucht; aber nicht einmal das klappt mehr ^^

Delphi-Quellcode:
procedure TForm1.SpeedButton4Click(Sender: TObject);
var
 untgesamt: integer;
 untfrequenz: integer;
 untwort: array of string;
 listitem: tlistitem;
 Textinhalt: Tstringlist;
 tokenlist: TStringlist;
 i,ii,iii: integer;
begin
  if untfilelist.Items.Count=0 then exit;
  //if reffilelist.Items.Count=0 then exit;

  speedbutton1.Enabled:=false;
  speedbutton2.Enabled:=false;

  {Jede Datei öffnen
  Funktion Tokens isolieren
  Tokens kopieren, falls vorhanden, frequenz erhöhen
  Tokens ausgeben}

  Try
  Textinhalt:= Tstringlist.Create;
  tokenlist:= tstringlist.create;

    // UntFileliste abarbeiten
    for i:=0 to untfilelist.Items.Count -1 do begin

      //File einlesen
      textinhalt.LoadFromFile(untfilelist.Items.Strings[i]);

      // Satzzeichen in Leerzeichen umwandeln
      textinhalt.Text:=stringreplace(textinhalt.Text,'.',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,',',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,';',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,'!',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,'?',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,':',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,'-',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,'"',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,'(',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,')',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,'[',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,']',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,'<',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,'>',' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,' ', ' ',[rfReplaceAll, rfIgnoreCase]);
      textinhalt.Text:=stringreplace(textinhalt.Text,' ', ' ',[rfReplaceAll, rfIgnoreCase]);

      //Geladenes File in Tokens zerlegen
      untgesamt:= Extractstrings([' '], [','], pchar(textinhalt.text), tokenlist);

      {Zerlegtes File in Array speichern, allerdings nur jedes Token einmal, zugleich zählen; Lösungsansatz: 1) Wort für Wort durchgehen; 2) bei jedem Wort nach gleichen Ausdrücken suchen; 3) wenn gleich, dann Audruck löschen und Zähler=zähler+1; am Ende direkt in die listbox ausgeben!}

      for ii:=0 to tokenlist.Count -1 do begin //Token der Liste durchgehen & ablesen
          untfrequenz := 1;
          //label Schleife;
          for iii:= ii+1 to tokenlist.count -1 do begin //Dasselbe Token in der Liste durchgehen und suchen
              if tokenlist.Names[ii] = tokenlist.names[iii] then begin // wenn gefunden, dann löschen und zählen
                 tokenlist.Delete(iii);
                 untfrequenz:= untfrequenz + 1;
                 //goto Schleife;
                 end
              else begin //wenn keine gleichen Tokens mehr gefunden werden, dann in Listview abspeichern
                   with untwortliste do begin
                     listitem := items.add;
                     listitem.caption:= tokenlist.names[ii];
                     listitem.subitems.add(inttostr(untfrequenz));
              end;
          end;

    //textansicht.Text :=tokenlist.Text //Test


  Finally
  Textinhalt.Free;
  tokenlist.free;
  end;
Zweck des Ganzen: Texte in ihre Tokens/Wörter zergliedern und die Wörter in einer Wortliste samt (Gesamt)Frequenz ausgeben.

Wäre für ein paar Tips, wie ich das lösen könnte, sehr dankbar!

Schönes WE und danke für Eure Mühe,
frieder

jaenicke 28. Feb 2009 04:16

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
Schau mal hier, da habe ich vor kurzem genau das geschrieben:
http://www.delphi-forum.de/viewtopic...=550678#550678
Du musst nur noch die Ergebnisliste dann in die ListView ausgeben.

frieder2008 28. Feb 2009 08:28

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
1) Hm, danke jaenicke, aber das klappt bei mir so nicht. Mein Problem ist ja, dass ich nur EINE Stringlist habe mit unterschiedlichen Strings. Die sollen in eine neue Stringlist zusammengefasst und mit der Häufigkeit ausgestattet werden. Ich hatte das bisher so versucht, dass ich

- Stringlist1 durchgegangen bin und z.B. WortX zusammenfassen wollte:
- Stringlist2 = Stringlist1 (einmalig)
- Stringlist2 durchgehen, ob WortX vorhanden; wenn ja, dann einen CounterInteger +1, den gefundenen Eintrag in Stringlist2 löschen und wieder von vorne Stringlist2 durchgehen, solange, bis in Stringlist2 alle WortX-Items gezählt und gelöscht sind.

Nur genau das bekomme ich so nicht hin. Ich bekommme (mit dem schon mal geposteten Code) eine Fehlermeldung, dass ich (vermutlich bei der Delete-Anweisung) einen ListCount überfordere.

Naja, hoffe, Du oder jemand anderes kann mir nochmal einen TIpp geben.

2) Eine Frage zu Deinem in dem anderen Thread geposteten Code:

Delphi-Quellcode:
  procedure CountOccurrences(const List1, List2: TStrings; var Result: TStrings);
  var
    i, CurIndex: Integer;
  begin
    for i := 0 to List1.Count - 1 do
      Result.AddObject(List1[i], TObject(0));
    for i := 0 to List2.Count - 1 do
    begin
      CurIndex := Result.IndexOf(List2[i]);
      if CurIndex >= 0 then
        Result.Objects[CurIndex] := TObject(Succ(Integer(Result.Objects[CurIndex])));
    end;
  end;
Ich wusste nicht, dass man einem TString ein "Object" beifügen kann; ich kenne diese Methode (als Anfänger) noch nicht; ich bin nur verwundert, weil ich dachte, dass man in einem TString eben nur 1 String, und zwar Zeile für Zeile fassen könnte.

Ich würd den Code gerne verstehen :)

Danke und viele Grüße zum Samstag,
frieder

jaenicke 28. Feb 2009 09:09

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
Zitat:

Zitat von frieder2008
1) Hm, danke jaenicke, aber das klappt bei mir so nicht. Mein Problem ist ja, dass ich nur EINE Stringlist habe mit unterschiedlichen Strings. Die sollen in eine neue Stringlist zusammengefasst und mit der Häufigkeit ausgestattet werden.

Fast exakt das macht mein Code. :mrgreen:
Der einzige Unterschied ist, dass du die selbe Liste 1 durchgehen musst.

Die von dir beschriebene Vorgehensweise ist ebenfalls identisch zu meiner, nur dass ich in der ersten Liste nichts lösche. Wofür auch, ich gehe einfach alle Einträge durch und suche nach jedem in der Ergebnisliste.

Zitat:

Zitat von frieder2008
Ich wusste nicht, dass man einem TString ein "Object" beifügen kann; ich kenne diese Methode (als Anfänger) noch nicht; ich bin nur verwundert, weil ich dachte, dass man in einem TString eben nur 1 String, und zwar Zeile für Zeile fassen könnte.

Eine TStringList ist genau wie auch die Zeilen von einem Memo z.B. von TStrings abgeleitet. In dieser Liste von Strings werden nicht nur die Strings sondern zu jedem String auch ein Objekt gespeichert, wenn der Benutzer das möchte.

So kannst du eine bestimmte Information zu jedem String speichern, in diesem Fall eben die Anzahl der Vorkommen in der ersten Liste.

frieder2008 28. Feb 2009 09:17

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
Hey thx,

ABER :)

Problem: Wenn ich deinen Code so mache und - da ich ja nur eine Stringlist habe, sie in eine andere kopiere und - beide an deine Countoccurence-Proc übergebe, dann passiert folgendes:

Stringlist beinhaltet:
eins
zwei
drei
zwei
eins

Ergebnis:
eins: 2
zwei: 2
drei: 1
zwei: 0
eins: 0

Das liegt daran, dass in der kopierten Stringlist ja auch alles doppelt vorhanden ist.
- Und jetzt fällt mir gerade ein, was ich tun könnte, dass es dennoch geht: Ich lösche die doppelten Einträge in dieser kopierten Stringlist heraus! :)

Nicht sehr elegant. Vielleicht weißt Du was besseres?

Danke und gruß,
frieder

jaenicke 28. Feb 2009 09:19

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
Ok, wie wäre es so (Zum Testen eine ListBox und ein Button): ;-)
Delphi-Quellcode:
procedure TForm149.Button1Click(Sender: TObject);

  procedure CountOccurrences(const MyList: TStrings; var Result: TStrings);
  var
    i, CurIndex: Integer;
  begin
    for i := 0 to MyList.Count - 1 do
    begin
      CurIndex := Result.IndexOf(MyList[i]);
      if CurIndex >= 0 then
        Result.Objects[CurIndex] := TObject(Succ(Integer(Result.Objects[CurIndex])))
      else
        Result.AddObject(MyList[i], TObject(1));
    end;
  end;

var
  TempList: TStrings;
  i: Integer;
begin
  TempList := TStringList.Create;
  try
    CountOccurrences(ListBox1.Items, TempList);
    for i := 0 to TempList.Count - 1 do
      ShowMessage(TempList[i] + ': ' + IntToStr(Integer(TempList.Objects[i])));
  finally
    TempList.Free;
  end;
end;

DeddyH 28. Feb 2009 09:31

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
Wieso übergibst Du Result als var-Parameter?

frieder2008 28. Feb 2009 10:00

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
Yepp, das funtzt. Unfair ;)

Danke und Gruß,
frieder

DeddyH 28. Feb 2009 10:02

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
Lass das var mal weg, sollte trotzdem funktionieren.

jaenicke 28. Feb 2009 10:23

Re: Einträge in Listview / Stringlist vergleichen;Strings zä
 
Klar tut es das, aber mit dem var sieht man klar, dass in diese Variable etwas reingelegt wird. Und deshalb bevorzuge ich diese Schreibweise. Die andere bekommt das const, weil diese nicht verändert wird.

Durch diese Schlüsselwörter sieht man sehr viel besser wie man eine fremde Methode benutzt finde ich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:07 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz