• 泛型排序器 TComparer


    测试代码文件:
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    type
      TForm1 = class(TForm)
        Memo1: TMemo;
        Memo2: TMemo;
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        Button4: TButton;
        Button5: TButton;
        Button6: TButton;
        Button7: TButton;
        Button8: TButton;
        Button9: TButton;
        Button10: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
        procedure Button5Click(Sender: TObject);
        procedure Button6Click(Sender: TObject);
        procedure Button7Click(Sender: TObject);
        procedure Button8Click(Sender: TObject);
        procedure Button9Click(Sender: TObject);
        procedure Button10Click(Sender: TObject);
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    uses Generics.Collections, Generics.Defaults; {必需的泛型单元}
    
    //构建由 10 个整数组成的动态数组, 然后排序
    procedure TForm1.Button1Click(Sender: TObject);
    var
      arr: array of Integer;
      i: Integer;
    begin
      {构建动态数组}
      Randomize;
      for i := 0 to 9 do begin
        SetLength(arr, Length(arr)+1);
        arr[i] := Random(10);
      end;
    
      {显示排序前}
      Memo1.Clear;
      for i := 0 to Length(arr) - 1 do Memo1.Lines.Add(IntToStr(arr[i]));
    
      {排序}
      TArray.Sort<Integer>(arr); {它可以有 1个、2个、4个参数, 这里只用了一个参数, 其他是默认参数}
    
      {显示排序结果}
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(IntToStr(arr[i]));
    end;
    
    // TArray.Sort 的第二个参数是 IComparer<T> 类型, 其默认值是: TComparer<T>.Default
    procedure TForm1.Button2Click(Sender: TObject);
    var
      arr: array of Integer;
      i: Integer;
    begin
      Randomize;
      for i := 0 to 9 do begin
        SetLength(arr, Length(arr)+1);
        arr[i] := Random(10);
      end;
    
      Memo1.Clear;
      for i := 0 to Length(arr) - 1 do Memo1.Lines.Add(IntToStr(arr[i]));
    
      {使用了排序器的默认值排序, 这和忽略这个参数是一样的}
      TArray.Sort<Integer>(arr, TComparer<Integer>.Default);
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(IntToStr(arr[i]));
    end;
    
    //同上两例, 变通了一下写法
    procedure TForm1.Button3Click(Sender: TObject);
    var
      arr: array of Integer;
      i: Integer;
      Comparer: IComparer<Integer>;
    begin
      Randomize;
      for i := 0 to 9 do begin
        SetLength(arr, Length(arr)+1);
        arr[i] := Random(10);
      end;
    
      Memo1.Clear;
      for i := 0 to Length(arr) - 1 do Memo1.Lines.Add(IntToStr(arr[i]));
    
      Comparer := TComparer<Integer>.Default;
      TArray.Sort<Integer>(arr, Comparer);
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(IntToStr(arr[i]));
    end;
    
    // TArray.Sort 的后面两个参数可以指定排序范围:
    procedure TForm1.Button4Click(Sender: TObject);
    var
      arr: array of Integer;
      i: Integer;
      Comparer: IComparer<Integer>;
    begin
      Randomize;
      for i := 0 to 9 do begin
        SetLength(arr, Length(arr)+1);
        arr[i] := Random(10);
      end;
    
      Memo1.Clear;
      for i := 0 to Length(arr) - 1 do Memo1.Lines.Add(IntToStr(arr[i]));
    
      Comparer := TComparer<Integer>.Default;
      {这里指定从第 1 个元素开始, 只给 3 个元素排序}
      TArray.Sort<Integer>(arr, Comparer, 0, 3);
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(IntToStr(arr[i]));
    end;
    
    //如果要倒排序, 可以建立自己的排序器, 下面就是先构建并实现了一个 TMyComparer, 然后调用:
    type
      TMyComparer = class(TComparer<Integer>)
      public
        function Compare(const Left, Right: Integer): Integer; override;
      end;
    
    { TMyComparer }
    function TMyComparer.Compare(const Left, Right: Integer): Integer;
    begin
      Result := Right - Left;
    end;
    
    procedure TForm1.Button5Click(Sender: TObject);
    var
      arr: array of Integer;
      i: Integer;
      Comparer: TMyComparer;
    begin
      Randomize;
      for i := 0 to 9 do begin
        SetLength(arr, Length(arr)+1);
        arr[i] := Random(10);
      end;
    
      Memo1.Clear;
      for i := 0 to Length(arr) - 1 do Memo1.Lines.Add(IntToStr(arr[i]));
    
      Comparer := TMyComparer.Create;
      TArray.Sort<Integer>(arr, Comparer);
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(IntToStr(arr[i]));
      Comparer.Free;
    end;
    
    
    // 也可以用 TComparer<T>.Construct 方法, 通过一个 TComparison 格式的函数构建排序器, 这样简单一些
    function MyFunc1(const Left, Right: Integer): Integer;
    begin
      Result := Right - Left;
    end;
    
    procedure TForm1.Button6Click(Sender: TObject);
    var
      arr: array of Integer;
      i: Integer;
      Comparer: IComparer<Integer>;
    begin
      Randomize;
      for i := 0 to 9 do begin
        SetLength(arr, Length(arr)+1);
        arr[i] := Random(10);
      end;
    
      Memo1.Clear;
      for i := 0 to Length(arr) - 1 do Memo1.Lines.Add(IntToStr(arr[i]));
    
      Comparer := TComparer<Integer>.Construct(MyFunc1);
      TArray.Sort<Integer>(arr, Comparer);
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(IntToStr(arr[i]));
    end;
    
    
    //如果是给自定义类型的元素排序, 只能是自建排序器
    type
      TPerson = record
        name: string;
        age: Word;
      end;
    
    function MyFunc2(const Left, Right: TPerson): Integer;
    begin
      Result := Left.age - Right.age;
    end;
    
    procedure TForm1.Button7Click(Sender: TObject);
    var
      arr: array of TPerson;
      i: Integer;
      Comparer: IComparer<TPerson>;
    begin
      SetLength(arr, 4);
      arr[0].name := 'AA'; arr[0].age := 22;
      arr[1].name := 'BB'; arr[1].age := 33;
      arr[2].name := 'CC'; arr[2].age := 44;
      arr[3].name := 'DD'; arr[3].age := 11;
    
      Memo1.Clear;
      for i := 0 to Length(arr) - 1 do
        Memo1.Lines.Add(Format('%s : %d', [arr[i].name, arr[i].age]));
    
      Comparer := TComparer<TPerson>.Construct(MyFunc2);
      TArray.Sort<TPerson>(arr, Comparer);
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do
        Memo2.Lines.Add(Format('%s : %d', [arr[i].name, arr[i].age]));
    end;
    
    // TStringComparer.Ordinal 是官方实现的用于 string 的排序器, 可直接使用.
    //但它好像有问题(Delphi 2010 - 14.0.3513.24210), 以后的版本应该能改过来.
    procedure TForm1.Button8Click(Sender: TObject);
    var
      arr: array of string;
      i: Integer;
    begin
      SetLength(arr, 4);
      arr[0] := '222';
      arr[1] := '111';
      arr[2] := 'bbb';
      arr[3] := 'aaa';
    
      Memo1.Clear;
      for i := 0 to Length(arr) - 1 do Memo1.Lines.Add(arr[i]);
    
      TArray.Sort<string>(arr, TStringComparer.Ordinal);
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(arr[i]);
    end;
    
    //下面是实现字符串数组的到排序
    function MyComparerFunc(const s1,s2: string): Integer;
    begin
      Result := CompareText(s2, s1);
      //Result := -CompareText(s1, s2); {或者这样}
    end;
    
    procedure TForm1.Button9Click(Sender: TObject);
    var
      arr: array of string;
      i: Integer;
      Comparer: IComparer<string>;
    begin
      Memo1.Clear;
      Memo1.Lines.CommaText := '11,33,22,AAA,CCC,BBB';
      SetLength(arr, Memo1.Lines.Count);
      for i := 0 to Length(arr) - 1 do arr[i] := Memo1.Lines[i];
    
      Comparer := TComparer<string>.Construct(MyComparerFunc);
      TArray.Sort<string>(arr, Comparer);
    
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(arr[i]);
    end;
    
    //可以把上一个程序简写为:
    procedure TForm1.Button10Click(Sender: TObject);
    var
      arr: array of string;
      i: Integer;
      Comparer: IComparer<string>;
    begin
      Memo1.Clear;
      Memo1.Lines.CommaText := '11,33,22,AAA,CCC,BBB';
      SetLength(arr, Memo1.Lines.Count);
      for i := 0 to Length(arr) - 1 do arr[i] := Memo1.Lines[i];
    
      Comparer := TComparer<string>.Construct(
        function (const s1,s2: string): Integer
        begin
          Result := CompareText(s2, s1);
        end);
      TArray.Sort<string>(arr, Comparer);
    
      Memo2.Clear;
      for i := 0 to Length(arr) - 1 do Memo2.Lines.Add(arr[i]);
    end;
    
    end.
    

    测试窗体文件(之所以附上窗体文件, 是为了再次测试方便):
    object Form1: TForm1
      Left = 0
      Top = 0
      Caption = 'Form1'
      ClientHeight = 321
      ClientWidth = 318
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object Memo1: TMemo
        Left = 0
        Top = 0
        Width = 89
        Height = 321
        Align = alLeft
        Lines.Strings = (
          'Memo1')
        TabOrder = 0
        ExplicitHeight = 299
      end
      object Button1: TButton
        Left = 120
        Top = 8
        Width = 75
        Height = 25
        Caption = 'Button1'
        TabOrder = 1
        OnClick = Button1Click
      end
      object Button2: TButton
        Left = 120
        Top = 39
        Width = 75
        Height = 25
        Caption = 'Button2'
        TabOrder = 2
        OnClick = Button2Click
      end
      object Button3: TButton
        Left = 120
        Top = 70
        Width = 75
        Height = 25
        Caption = 'Button3'
        TabOrder = 3
        OnClick = Button3Click
      end
      object Memo2: TMemo
        Left = 219
        Top = 0
        Width = 99
        Height = 321
        Align = alRight
        Lines.Strings = (
          'Memo2')
        TabOrder = 4
        ExplicitHeight = 299
      end
      object Button4: TButton
        Left = 120
        Top = 101
        Width = 75
        Height = 25
        Caption = 'Button4'
        TabOrder = 5
        OnClick = Button4Click
      end
      object Button5: TButton
        Left = 120
        Top = 132
        Width = 75
        Height = 25
        Caption = 'Button5'
        TabOrder = 6
        OnClick = Button5Click
      end
      object Button6: TButton
        Left = 120
        Top = 163
        Width = 75
        Height = 25
        Caption = 'Button6'
        TabOrder = 7
        OnClick = Button6Click
      end
      object Button7: TButton
        Left = 120
        Top = 194
        Width = 75
        Height = 25
        Caption = 'Button7'
        TabOrder = 8
        OnClick = Button7Click
      end
      object Button8: TButton
        Left = 120
        Top = 225
        Width = 75
        Height = 25
        Caption = 'Button8'
        TabOrder = 9
        OnClick = Button8Click
      end
      object Button9: TButton
        Left = 120
        Top = 256
        Width = 75
        Height = 25
        Caption = 'Button9'
        TabOrder = 10
        OnClick = Button9Click
      end
      object Button10: TButton
        Left = 120
        Top = 287
        Width = 75
        Height = 25
        Caption = 'Button10'
        TabOrder = 11
        OnClick = Button10Click
      end
    end
    
  • 相关阅读:
    内部类,匿名内部类?
    抽象和接口的区别?
    多态的好处?
    怎么防止重复提交?
    java网络编程第二章
    java网络编程第一章
    多态的好处
    静态变量与实例变量(方法)的区别
    杨辉三角
    鸿蒙系统之内核层
  • 原文地址:https://www.cnblogs.com/del/p/1580390.html
Copyright © 2020-2023  润新知