Domanda

Ho due liste di stringhe che sto lavorando con. Uno che ha una lista di parole chiave, e poi un altro che ha una lista di parole chiave negativa. Voglio essere in grado di cercare attraverso la lista e scegliere le voci di elenco che non contengono la parola chiave negativa e di uscita a un terzo elenco di parole chiave. Stavo usando la funzione AnsiPos ma che ha trovato le parole chiave negativa se fossero parte di una parola, contro l'intera parola.

Qualche suggerimento su un modo relativamente semplice per fare questo? La velocità non è così importante, ma sarebbe bello.

Esempio di quello che sto cercando di fare:

Elenco parole chiave:

Cat 
Catfish
Fish Sticks
Dog Food

Negativo elenco di parole chiave:

Fish

valori restituiti Cerchiamo

Cat 
Catfish
Dog Food

Questo è quello che ho finora .. che non funziona. Ho usato le informazioni da: C'è un efficiente Ricerca a Word funzione in Delphi?

function ExistWordInString(aString: PAnsichar; aSearchString: string;
  aSearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
begin
  Size := StrLen(aString);
  result := SearchBuf(aString, Size, 0, 0, aSearchString, aSearchOptions) <> nil;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  i, j, index: integer;
  s: string;
  stl: tstringlist;
begin
  stl := TStringList.Create;
  stl.Text := listbox1.Items.Text;
  for I := 0 to stl.Count - 1 do
  begin
    for j := 0 to listbox2.Count - 1 do
    begin
      if not ExistWordInString(PAnsiChar(listbox2.Items.Strings[j]),
        listbox1.Items.Strings[i], [soWholeWord, soDown])
      then
        listbox3.Items.Append(stl.Strings[i]);
    end;
  end;
end;
È stato utile?

Soluzione

questo codice di esempio funziona come un fascino (utilizzando Delphi 7):

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, StrUtils;

type
  TForm1 = class(TForm)
  Button1: TButton;
  ListBox1: TListBox;
  ListBox2: TListBox;
  ListBox3: TListBox;
  procedure Button1Click(Sender: TObject);

  private
     function ExistWordInString(aString, aSearchString:string;aSearchOptions: TStringSearchOptions): Boolean;

  public
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
    i,k: integer;

begin

    for k:= 0 to ListBox2.Count -1 do
        for i:= 0 to ListBox1.Count - 1 do
        begin
            if not ExistWordInString(ListBox1.Items[i], ListBox2.Items[k],[soWholeWord,soDown]) then
                ListBox3.Items.Append(ListBox1.Items[i]);
        end;

end;

function TForm1.ExistWordInString(aString, aSearchString: string; aSearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;

begin
        Size:=Length(aString);
        Result := SearchBuf(PChar(aString), Size, 0, 0, aSearchString, aSearchOptions)<>nil;

end;
end.    

ed ecco la forma:

object Form1: TForm1
  Left = 1008
  Top = 398
  Width = 411
  Height = 294
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 320
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object ListBox1: TListBox
    Left = 8
    Top = 8
    Width = 177
    Height = 97
    ItemHeight = 13
    Items.Strings = (
      'Cat '
      'Catfish'
      'Fish Sticks'
      'Dog Food')
    TabOrder = 1
  end
  object ListBox2: TListBox
    Left = 192
    Top = 8
    Width = 121
    Height = 97
    ItemHeight = 13
    Items.Strings = (
      'Fish')
    TabOrder = 2
  end
  object ListBox3: TListBox
    Left = 8
    Top = 112
    Width = 305
    Height = 137
    ItemHeight = 13
    TabOrder = 3
  end
end

Spero che questo aiuti.

Reinhard: -)

Altri suggerimenti

Se gli spazi sono l'unica parola delimitatore è necessario preoccuparsi, allora si può fare una partita di parola intera utilizzando AnsiPos con l'aggiunta di uno spazio prima e dopo il sia la parola chiave e la parola chiave negativa, vale a dire

AnsiPos ( ' '+ SubStr +'', ' '+ Str +'')

Avreste bisogno di un ciclo per controllare ogni voce dall'elenco parole chiave negativa.

Credo di aver capito. Utilizzare stringlist.find ( 'pesce', indice);

Non ho capirlo. .find non ha funzionato.

-Brad

È possibile utilizzare la funzione SearchBuf (vedi la risposta del pastacool) se si è non interessati ad altri personaggi, ad eccezione A..Z / Unicode.

Se si dispone di un Unicode Delphi (D2009 o D2010), allora è necessario utilizzare TCharacter.IsLetterOrDigit (aString: string; aIndex: integer): booleano; dalla Carattere unità. Un semplice esempio per voi per ottenere l'idea:

procedure TForm7.btn1Click(Sender: TObject);
var
  bMatches: boolean;

begin
  with rgx1 do //custom component - disregard it
  begin
    RegEx:=edtTextToFind.Text; //text to find
    Subject:=mmoResult.Text; //text in which to search
    if Match then //aha! found it!
    begin
      bMatches:=True;
      if chkWholeWord.Checked then //be attentive from here!! - I think that's self explaining...
      begin
        if MatchedExpressionOffset>1 then
          bMatches:=not TCharacter.IsLetterOrDigit(Subject, MatchedExpressionOffset-1);
        if bMatches and (MatchedExpressionOffset+MatchedExpressionLength<=Length(Subject)) then
          bMatches:=not TCharacter.IsLetterOrDigit(Subject, MatchedExpressionOffset+MatchedExpressionLength);
      end;
      if bMatches then //select it in the memo
      begin
        mmoResult.SelStart:=MatchedExpressionOffset-1;
        mmoResult.SelLength:=MatchedExpressionLength;
        mmoResult.SetFocus;
      end
      else
        ShowMessage('Text not found!');
    end
    else
      ShowMessage('Text not found!');
  end;
end;

Cambia la funzione per leggere:

function ExistWordInString(aString:PAnsichar;
   aSearchString:string;
   aSearchOptions: TStringSearchOptions): Boolean;
var 
  b : boolean;
begin
  if soWholeWord in aSearchOptions then
    b := Pos(' '+Uppercase(aSearchString)+' ',' '+UpperCase(aString)+' ') > 0;
  else
    b := Pos(UpperCase(aSearchString),UpperCase(aString)) > 0;
  Result := b;
end;

Se la vostra utilizzando Delphi 2009/2010 poi cambiarlo da Pos a AnsiPos. La mia ipotesi è che soWholeWord significa che la partita "Fish" potrebbe corrispondere a "bastoncini di pesce" ma non "pesce gatto".

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top