数组类型有方法吗?

Fab*_*zio 5 arrays delphi

我已经定义了一个动态数组类型如下:

TMyIntegerArray = array of integer:
Run Code Online (Sandbox Code Playgroud)

IndexOf如果它是一个TObject后代我想使用一个函数:

var
  MyArray : TMyIntegerArray;
  i : integer:
begin
  //...
  i := MyArray.IndexOf(10);
  //...
end;
Run Code Online (Sandbox Code Playgroud)

目前,我发现的唯一解决方案是编写一个接受数组和目标值作为参数的函数:

function IndexOf(AArray : TMyIntegerArray; ATargetValue : integer; AOffset : integer = 0);
begin
  Result := AOffset;
  while(Result < Length(AArray)) do
  begin
    if(AArray[Result] = ATargetValue)
    then Exit;
    Result := Result + 1;
  end;
  Result := -1;
end;
Run Code Online (Sandbox Code Playgroud)

可以TMyIntegerArray输入类似的功能IndexOf吗?

更多信息:

目前,我正在使用Delphi2007,但我也有兴趣知道是否有任何方法可以在更新的Delphi版本中为数组类型添加方法.

LU *_* RD 13

在较新版本的Delphi(XE3 +)中,可以使用以下方法实现数组类型的方法record helpers:

program ProjectTest;

{$APPTYPE CONSOLE}

Type
  TMyArray = array of integer;

  TMyArrayHelper = record helper for TMyArray
    procedure Print;
    function IndexOf(ATargetValue : integer; AOffset : integer = 0): Integer;
  end;

procedure TMyArrayHelper.Print;
var
  i: Integer;
begin
  for i in Self do WriteLn(i);  // Use Self for variable reference
end;

function TMyArrayHelper.IndexOf(ATargetValue : integer; AOffset : integer = 0): Integer;
begin
  Result := AOffset;
  while(Result < Length(Self)) do
  begin
    if(Self[Result] = ATargetValue)
    then Exit;
    Result := Result + 1;
  end;
  Result := -1;
end;

var
  myArr : TMyArray;
begin
  myArr := [0,1,2];  // A neat way to populate a dynamic array (XE7+)
  myArr.Print;
  WriteLn(myArr.IndexOf(2));

  ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)

注意:您可以跳过TMyArray类型声明并使用TArray<Integer>更宽松的类型解析.与记录助手一样,一个类型只能连接一个助手(将使用的助手是最接近范围的助手).

这种类型的帮助程序称为内部类型帮助程序,其中编译器在类型周围放置隐式记录结构.

  • 嗯,我不知道.谢谢. (3认同)

Uwe*_*abe 6

尽管LU RD显示了您问题的直接解决方案,但我将基于泛型添加略有不同的方法.这具有在一个地方为不同阵列类型提供有效解决方案的优点.

对于支持泛型的Delphi版本,可以采用System.Generics.Collections中的TArray中使用的方式.这是引入函数IndexOf的类的直接扩展:

type
  TArrayExt = class(TArray)
  public
    class function IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count:
        Integer): Integer; overload; static;
    class function IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>): Integer; overload;
        static;
    class function IndexOf<T>(const Values: array of T; const Item: T): Integer; overload; static;
  end;

class function TArrayExt.IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index,
    Count: Integer): Integer;
var
  I: Integer;
begin
  if (Index < Low(Values)) or ((Index > High(Values)) and (Count > 0))
    or (Index + Count - 1 > High(Values)) or (Count < 0)
    or (Index + Count < 0) then
    raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  if Count = 0 then
  begin
    Exit(-1);
  end;
  for I := Index to Index + Count - 1 do begin
    if Comparer.Equals(Item, Values[I]) then begin
      Exit(I);
    end;
  end;
  Result := -1;
end;

class function TArrayExt.IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>): Integer;
begin
  Result := IndexOf<T>(Values, Item, Comparer, Low(Values), Length(Values));
end;

class function TArrayExt.IndexOf<T>(const Values: array of T; const Item: T): Integer;
begin
  result := IndexOf<T>(Values, Item, TEqualityComparer<T>.Default, Low(Values), Length(Values));
end;
Run Code Online (Sandbox Code Playgroud)

一个简单的用例可能如下所示:

procedure Main;
var
  arr: TArray<Integer>;
  N: Integer;
begin
  arr := TArray<Integer>.Create(5, 7, 3, 4, 2);
  repeat
    Readln(N);
    N := TArrayExt.IndexOf(arr, N);
    Writeln(N);
  until false;
end;
Run Code Online (Sandbox Code Playgroud)