关键:Find要事先Sort排序,Indexof不用排序。

TStringList内部查找相关的数据。待调试代码时才知道痛苦,浪费无数时间后,只得一步步跟踪,才发

现Find方法返回的Index总是错误的,当时一阵郁闷,随手按下F1键,Find的Help文档展现眼前,对于该

函数是这样描述的:
Locates the index for a string in a sorted list and indicates whether a string with that

value already exists in the list.

在Note部分又再次强调:

Only use Find with sorted lists. For unsorted lists, use the IndexOf method instead.

只怪自己一时懒惰,在不了解的情况下便抛弃习惯了的IndexOf,轻易使用新函数。但同时我也来了兴趣,为什么Find只能在使用TStringList.Sort方法后才能正常返回数据呢?

老办法,直接跳到Classes文件中查看源代码:

function TStringList.Find(const S: string; var Index: Integer): Boolean;
var
L, H, I, C: Integer;
begin
Result := False;
L := 0;
H := FCount - 1;
while L <= H do
begin
    I := (L + H) shr 1;
    C := CompareStrings(FList^[I].FString, S);
    if C < 0 then L := I + 1
    else begin
      H := I - 1;
      if C = 0 then
      begin
        Result := True;
        if Duplicates <> dupAccept then L := I;
      end;
    end;
end;
Index := L;
end;

还是被吓了一跳,怎么感觉这么复杂,仔细一看才明白,原来是个折半查找算法。呵呵。
L,H变量分别代表Low和High,(L + H) shr 1就是求中间值的,完全等于(L + H) div 2,对于二进制,

右移一位就相当于整除2。其中CompareStrings是用来对比两个字符串大小的:

function TStringList.CompareStrings(const S1, S2: string): Integer;
begin
if CaseSensitive then
    Result := AnsiCompareStr(S1, S2)
else
    Result := AnsiCompareText(S1, S2);
end;

这里的CaseSensitive用来标记是否大小写敏感,AnsiCompareStr是大小写敏感的,AnsiCompareText则

反之。另外在Help文档中还特地说明了两个函数进行判断时,小写字符是小于大写字符的,比如'a'<'A'

。请注意,这一点是与ASCII不相同的地方(如果再跟下去,你可以发现这两个函数是对API的一个封装,

而且封装了Linux和Windows的两个版本)。

此时我们返回到Find函数本身,又会发现在判断条件中只有C<0和C=0的情况,也就是说它只能搜索升序

排列的StringList。

忍不住,再看了看Sort方法。

procedure TStringList.Sort;
begin
CustomSort(StringListCompareStrings);
end;

简单的不能再简单,一行语句。CustomSort是一个公共方法,供用户使用自定义的比较规则进行排序。

StringListCompareStrings参数中放置的就是自定义比较规则的函数:

TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer;

CustomSort的代码如下:

procedure TStringList.CustomSort(Compare: TStringListSortCompare);
begin
if not Sorted and (FCount > 1) then
begin
    Changing;
    QuickSort(0, FCount - 1, Compare);
    Changed;
end;
end;

Changing和Changed主要是用来触发FOnChanging和FOnChanged的,具体内容可以自己看代码。而

QuickSort则是使用快速排序算法和用户自定义的比较规则进行排序了,再跟入到QuickSort代码中:
procedure TStringList.QuickSort(L, R: Integer; SCompare: TStringListSortCompare);
var
I, J, P: Integer;
begin
repeat
    I := L;
    J := R;
    P := (L + R) shr 1;
    repeat
      while SCompare(Self, I, P) < 0 do Inc(I);
      while SCompare(Self, J, P) > 0 do Dec(J);
      if I <= J then
      begin
        ExchangeItems(I, J);
        if P = I then
          P := J
        else if P = J then
          P := I;
        Inc(I);
        Dec(J);
      end;
    until I > J;
    if L < J then QuickSort(L, J, SCompare);
    L := I;
until I >= R;
end;

哈哈,正是这一段

while SCompare(Self, I, P) < 0 do Inc(I);
while SCompare(Self, J, P) > 0 do Dec(J);

使得TStringList是按照升序排列。至此,大致原因弄明白了。

再看看IndexOf是如何实现搜索的,刚开始我认为它肯定是使用For循环遍历每个Item,遇到相同的内容

则跳出循环,结果发现它确实也是这么做的,只是中间做了一些优化,假如StringList已经排序过,它

会自动使用效率更高的Find方法进行查找,另外它使用Result作为循环变量,对资源的利用极其充分。

代码如下:

function TStringList.IndexOf(const S: string): Integer;
begin
if not Sorted then Result := inherited IndexOf(S) else
    if not Find(S, Result) then Result := -1;
end;

其中继承使用了父类TStrings中的IndexOf方法

function TStrings.IndexOf(const S: string): Integer;
begin
for Result := 0 to GetCount - 1 do
    if CompareStrings(Get(Result), S) = 0 then Exit;
Result := -1;
end;

这段代码中的Get方法在TStrings中则是纯虚函数。

function Get(Index: Integer): string; virtual; abstract;

纯虚函数怎么能用,倒。那既然能用,只有一个可能,就是子类TStringList中实现了Get方法。返回到

TStringList中,在果然看到以下代码:

function TStringList.Get(Index: Integer): string;
begin
if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index);
Result := FList^[Index].FString;
end;

他用来取得指定行的字符串。分析也就此结束。

》》》》》》》》》》》》》》》》》》》》》》》》》》》》

Find是折半查找,速度应当是最快了,而indexof默认是 for 轮回所有item了。 但find应用前必须先排序 sort 不然返回 index错误。

示例如下:

var  lst:TStringList ;
     i:Integer ;
begin

lst:=TStringList.Create ;

try

lst:=TStringList.Create ;
    lst.CaseSensitive :=true;
    lst.Delimiter :="","";
    lst.DelimitedText :=Edit1.Text ;

ShowMessage(IntToStr(lst.IndexOf(Edit2.Text) ));
    lst.Sort ;
        if lst.Find(Edit2.Text ,i) then
      ShowMessage(IntToStr(i));
  finally

lst.Free ;
  end;

eidt2 内容 如下字符串  010a,010A,200a,200b,905a

Delphi : TStringList的Find,IndexOf和Sort的更多相关文章

  1. (转载)Delphi TStringList的用法

    Delphi TStringList的用法 TStrings是一个抽象类,在实际开发中,是除了基本类型外,应用得最多的. TStringList 常用方法与属性: var List: TStringL ...

  2. Delphi TStringList的用法

    Delphi TStringList的用法 TStrings是一个抽象类,在实际开发中,是除了基本类型外,应用得最多的. TStringList 常用方法与属性: var List: TStringL ...

  3. delphi TStringList 用法详解

    转自: http://blog.163.com/you888@188/blog/static/67239619201472365642633/ delphi TStringList 用法详解 2014 ...

  4. TStringList的Find,IndexOf和Sort

    procedure TForm1.Button1Click(Sender: TObject); var MyList: TStringList; begin MyList := TStringList ...

  5. Delphi TstringList Stringlist的特殊用法

    procedure TForm1.btn1Click(Sender : TObject); var   m      : Integer;   s       : string;   strlst   ...

  6. 删除delphi组件TStringlist中的重复项目

    https://blog.csdn.net/ozhy111/article/details/87975663 删除delphi组件TStringlist中的重复项目 2019年02月27日 15:41 ...

  7. 教程-TObjectList.Clear、TStringList.Clear方法对象有没有被释放

    相关资料: http://www.cnblogs.com/rogge7/p/4631796.html delphiTStringList通过AddObject方法添加对象. object里存的只是指向 ...

  8. Delphi 快速读取TXT 指定行的数据

    http://blog.csdn.net/MichaelJScofield/article/details/41869785 Delphi 快速读取TXT 指定行的数据 分类:Delphi个人挫品 ( ...

  9. iOS - Swift Swift 语言新特性

    1.Swift 2.0 带来哪些新变化 常规变化: 1.OS X 10.11.iOS 9 和 watchOS 2 SDK 采纳了一些 Objective-C 的特性用来提高 Swift 的编程体验, ...

随机推荐

  1. Tiny C Compiler简介-wiki

    Tiny C Compiler(缩写为TCC.tCc或TinyCC)是一个用于x86(16/32位)或x86-64(64位)系统的C编译器,开发者为Fabrice Bellard.软件是设计用于低级计 ...

  2. Apollo简介及工作原理

    一.Apollo简介 1.Apollo是携程框架部门研发的分布式配置中心 2.集中化管理应用的不同环境和不同集群的配置 3.配置修改后能够实时推送到应用端 4.具备规范的权限.流程治理等特性 二.Ap ...

  3. 2.1 什么是C++

    C++是一种通用程序设计语言,特别是面向系统程序设计. 1:是一个更好的C 2:支持数据抽象 3:支持面向对象的程序设计 4:支持通用型程序设计

  4. linux学习6 Linux系统组成及初始

    一.linux发行版回顾 1.版本回顾 2.Linux基础 a.CPU架构 32位CPU: X86 64位CPU:X64因为最早的X64位CPU是amd公司生产的所以也叫 amd64(可以兼容X86) ...

  5. YAML_06 playbook从上往下顺序执行,若报错,不提示,继续往下执行

    ansible]# vim user4.yml --- - hosts: cache   remote_user: root   vars:     user: bb   tasks:    - sh ...

  6. 卡林巴琴谱&简谱

    ---------------------------------------------------------------------------------------------------- ...

  7. Linux学习建议[转]

    端正学习态度学linux不会为了当黑客或者骇客,如果你为了当黑客或骇客而学习Linux,那么你离进监狱不远了,只是时间早晚而已.很多小白都知道“黑客攻击工具”很多来源与Linux平台上的,我也曾指导过 ...

  8. luogu P1058 立体图

    做了这个题后明确了自己的定位... 恩...普及- 题目大意估计都知道.. 给个传送门:   luogu 做了半上午 + 一整个下午的题... 占了我今天到的绝大多数时间. 其实此题不难, 核心代码我 ...

  9. UOJ422. 【集训队作业2018】小Z的礼物 [min-max容斥,插头DP]

    UOJ 思路 由于没有代码和AC记录的支撑,以下思路可能有错. 看到全部取完,大概可以想到min-max容斥. 由于期望的表达式里面合法方案的个数是在分母里面的,所以可以想到把它记录在状态里. 然而由 ...

  10. SpaceClaim脚本功能(Beta功能)

    本操作仅适用ANSYS SpaceClaim 2016 打开SpaceClaim脚本编辑器的方法有两种 方法一(看截图操作):         方法二(请见后面的实例操作). 创建球体源代码: #定义 ...