Delphi字符串列表在列表中查找否定关键字

发布于 2024-08-17 02:22:58 字数 1313 浏览 10 评论 0原文

我正在使用两个字符串列表。一个具有关键字列表,另一个具有否定关键字列表。我希望能够搜索列表并挑选出不包含否定关键字的列表项并输出到第三个关键字列表。我使用的是 AnsiPos 函数,但如果否定关键字是单词的一部分,而不是完整的单词,那么它会找到否定关键字。

关于相对简单的方法有什么建议吗?速度不是那么重要,但会很好。

我想要做的示例:

关键字列表:

Cat 
Catfish
Fish Sticks
Dog Food

否定关键字列表:

Fish

想要的返回值:

Cat 
Catfish
Dog Food

这是我到目前为止所得到的......但不起作用。我使用的信息来自:是否有高效的全词搜索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;

I have two string lists that I'm working with. One that has a list of keywords, and then another that has a list of negative keywords. I want to be able to search through the list and pick out the list items that do not contain the negative keyword and output to a third keyword list. I was using the AnsiPos function but that found the negative keywords if they were part of a word, vs full word.

Any suggestions on a relatively easy way to do this? Speed is not that important, but would be nice.

Example of what I'm looking to do:

Keyword List:

Cat 
Catfish
Fish Sticks
Dog Food

Negative Keyword List:

Fish

Returned Values Wanted:

Cat 
Catfish
Dog Food

This is what I've got so far.. which does not work. I used information from: Is There An Efficient Whole Word Search Function 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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

半世蒼涼 2024-08-24 02:22:58

如果空格是您需要担心的唯一单词分隔符,那么您可以使用 AnsiPos 进行整个单词匹配,方法是在关键字和否定关键字之前和之后添加空格,即

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

您需要一个循环来检查否定关键字列表中的每个条目。

If spaces are the only word delimiter you need to worry about, then you can do a whole word match using AnsiPos by adding a space before and after both the keyword and the negative keyword, ie

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

You'd need a loop to check every entry from the negative keyword list.

终止放荡 2024-08-24 02:22:58

这个示例代码的工作方式就像一个魅力(使用 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.    

形式如下:

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

希望这会有所帮助。

莱因哈特:-)

this sample code works like a charm (using 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.    

and here's the form:

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

hope this helps.

Reinhard :-)

情愿 2024-08-24 02:22:58

我想我已经明白了。使用 stringlist.find('fish',index);

我没弄清楚。 .find 不起作用。

-布拉德

I think I figured it out. Use stringlist.find('fish',index);

I didn't figure it out. .find did not work.

-Brad

格子衫的從容 2024-08-24 02:22:58

您可以使用 SearchBuf 函数(请参阅 Pastacool 的答案)如果您对除 A..Z / Unicode 之外的其他字符感兴趣。

如果您有 Unicode Delphi(D2009 或 D2010),则必须使用 Character 单元中的 TCharacter.IsLetterOrDigit(aString: string; aIndex: integer): boolean; 。一个简单的例子让你明白这个想法:

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;

You can use the SearchBuf function (see the pastacool's answer) IF you are not interested in other characters except A..Z / Unicode.

If you have an Unicode Delphi (D2009 or D2010) then you must use TCharacter.IsLetterOrDigit(aString: string; aIndex: integer): boolean; from the Character unit. A simple example for you to get the 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;
溇涏 2024-08-24 02:22:58

将您的函数更改为:

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;

如果您使用 Delphi 2009/2010,则将其从 Pos 更改为 AnsiPos。我在这里的假设是 soWholeWord 意味着匹配“Fish”将匹配“Fish Sticks”,但不匹配“catfish”。

Change your function to read:

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;

If your using Delphi 2009/2010 then change it from Pos to AnsiPos. My assumption here is that soWholeWord means that the match "Fish" would match "Fish Sticks" but not "catfish".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文