数组类型有方法吗?

时间:2017-03-13 15:18:27

标签: arrays delphi

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

TMyIntegerArray = array of integer:

我想使用IndexOf函数,如果它是TObject的后代,我会这样做:

var
  MyArray : TMyIntegerArray;
  i : integer:
begin
  //...
  i := MyArray.IndexOf(10);
  //...
end;

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

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;

TMyIntegerArray类型可以使用IndexOf等函数吗?

更多信息:

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

3 个答案:

答案 0 :(得分: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.

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

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

答案 1 :(得分: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;

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

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;

答案 2 :(得分:1)

对于Delphi 2009及更高版本,您可以使用通用列表:

uses System.Generic.Collections;

var
    MyArray : TList<integer>;
    i : integer;

begin
   MyArray := TList<integer>.Create;
   MyArray.Add(3);
   MyArray.Add(7);
   MyArray.Add(10);
   i := MyArray.IndexOf(10);
end;

在Delphi 2007中,您可以使用自定义记录:

type
   TMyArray = record
     private
      TheArray : array of integer;
     public
      procedure Add(Value : integer);
      function  IndexOf(Value : integer) : integer;
      function  Length : integer;
   end;   

procedure TMyArray.Add(Value : integer);

var
   i : integer;

begin
   i := length(TheArray);
   setlength(TheArray,i+1);
   TheArray[i] := Value; 
end;

function TMyArray.IndexOf(Value : integer) : integer;

var
   i : integer;

begin
   for i := 0 to length(TheArray)-1 do
      begin
         if TheArray[i] = Value then
            begin
               Result := i;
               exit; 
            end;
      end;
   Result := -1;
end;

function TMyArray.Length : integer;

begin
   Result := length(TheArray);
end;


procedure MyFunction;

  var
     MyArray : TMyArray;
     i : integer;

  begin
     MyArray.Add(3);
     MyArray.Add(7);
     MyArray.Add(10);
     i := MyArray.IndexOf(10);
  end;