【问题标题】:Delphi stringlist finding negative keyword in listDelphi stringlist在列表中查找否定关键字
【发布时间】:2011-01-03 14:33:25
【问题描述】:

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

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

我想要做的示例:

关键字列表:

猫 鲶鱼 鱼棒 狗粮

否定关键字列表:

想要的返回值:

猫 鲶鱼 狗粮

这是我到目前为止所得到的......这是行不通的。我使用的信息来自: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;

【问题讨论】:

    标签: delphi keyword tstringlist


    【解决方案1】:

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

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

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

    【讨论】:

    • 这可能行得通......虽然看起来有点像黑客......但它会比我现在做的更容易......:P
    【解决方案2】:

    这个示例代码就像一个魅力(使用 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
    

    希望这会有所帮助。

    莱因哈德:-)

    【讨论】:

    • 感谢所有为此提供帮助的人。这非常适合我的需求!我只是希望它在升级时能与 Delphi 10 一起使用。
    【解决方案3】:

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

    我没弄明白。 .find 不起作用。

    -布拉德

    【讨论】:

    • ps。为了提高性能,请查看 .Sorted 属性,它有助于 .Find 更快地完成工作。
    • 这行不通。 “查找”不匹配部分字符串。您将需要一些算法来为否定列表中的每个单词与候选列表执行“整个单词”匹配比较。您对“整个单词”的定义可能非常具体(即“空格”和“字符串开头/字符串结尾”之外的哪些字符构成了用于匹配“单词”的断字。
    • 正如 Jolyon 所指出的,这是一个错误的答案。请不要投票。
    • 感谢大家的帮助,除非您能想到更好的方法,否则我将尝试类似:stackoverflow.com/questions/1678572/…
    【解决方案4】:

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

    如果你有一个 Unicode Delphi(D2009 或 D2010),那么你必须使用 TCharacter.IsLetterOrDigit(aString: string; aIndex: integer): boolean; 来自 Character单元。一个简单的例子让你明白:

    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;
    

    【讨论】:

      【解决方案5】:

      将你的函数改为阅读:

      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”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多