如何获得通用TList <integer>?</integer>中的最大值

时间:2013-01-03 13:25:33

标签: delphi delphi-xe2

TList<Integer>中获取最大值的最简单方法是什么?

function GetMaximum(AList: TList<Integer>): Integer;
begin
  Assert(AList.Count > 0);
  Result := ?;
end;

我读到C#有一个AList.Max,在Delphi中有类似的东西吗?

4 个答案:

答案 0 :(得分:10)

这是一个在通用容器上实现MaxValue的有趣示例:

{$APPTYPE CONSOLE}

uses
  System.SysUtils, System.Generics.Defaults, System.Generics.Collections;

type
  TMyList<T> = class(TList<T>)
  public
    function MaxValue: T;
  end;

{ TMyList<T> }

function TMyList<T>.MaxValue: T;
var
  i: Integer;
  Comparer: IComparer<T>;
begin
  if Count=0 then
    raise Exception.Create('Cannot call TMyList<T>.MaxValue on an empty list');
  Comparer := TComparer<T>.Default;
  Result := Self[0];
  for i := 1 to Count-1 do
    if Comparer.Compare(Self[i], Result)>0 then
      Result := Self[i];
end;

var
  IntList: TMyList<Integer>;
  DoubleList: TMyList<Double>;
  StringList: TMyList<string>;

begin
  IntList := TMyList<Integer>.Create;
  IntList.AddRange([10, 5, 12, -49]);
  Writeln(IntList.MaxValue);

  DoubleList := TMyList<Double>.Create;
  DoubleList.AddRange([10.0, 5.0, 12.0, -49.0]);
  Writeln(DoubleList.MaxValue);

  StringList := TMyList<string>.Create;
  StringList.AddRange(['David Heffernan', 'Uwe Raabe', 'Warren P', 'Jens Mühlenhoff']);
  Writeln(StringList.MaxValue);

  Readln;
end.

因为我们无法提出与low(Integer)的通用等价物,所以当在空列表上调用该方法时,我会引发异常。

输出结果为:

12
 1.20000000000000E+0001
Warren P

答案 1 :(得分:8)

以下是另一种答案:使用Spring4D框架中的Spring.Collections.pas单元:(在此处找到:http://code.google.com/p/delphi-spring-framework/

program ListEnumerableDemo;

{$APPTYPE CONSOLE}

uses 
    System.SysUtils 
  , Spring.Collections;

var 
  List: IList<Integer>; 
  Enumerable: IEnumerable<Integer>;

begin 
  try 
    List := TCollections.CreateList<Integer>; 
    List.AddRange([1,6,2,9,54,3,2,7,9,1]);

    Enumerable := List; 
    WriteLn(Enumerable.Max); 
    ReadLn; 
  except 
    on E: Exception do 
      Writeln(E.ClassName, ': ', E.Message); 
  end; 
end. 

答案 2 :(得分:3)

使用for .. in

function GetMaximum(AList: TList<Integer>): Integer;
var
  I: Integer
begin
  Assert(AList.Count > 0);
  Result := Low(Integer);
  for I in AList do
    if I > Result then
      Result := I;
end;

答案 3 :(得分:1)

我同意使用Spring集合可能是最简单的方法。但是可能有理由不使用它们(已经在整个地方使用了Generics.Collections)。

以下是如何制作一个使用TEnumerable<T>扩展function Max: T的新类型。

type
  Enumerable<T> = record
  private
    source: TEnumerable<T>;
  public
    function Max: T;

    class operator Implicit(const value: TEnumerable<T>): Enumerable<T>;
  end;

class operator Enumerable<T>.Implicit(
  const value: TEnumerable<T>): Enumerable<T>;
begin
  Result.source := value;
end;

function Enumerable<T>.Max: T;
var
  default: IComparer<T>;
  x, y: T;
  flag: Boolean;
begin
  if not Assigned(source) then
    raise EArgumentNilException.Create('Source');
  default := TComparer<T>.Default;

  flag := False;
  for x in source do
  begin
    if flag then
    begin
      if default.Compare(x, y) > 0 then
        y := x;
    end
    else
    begin
      y := x;
      flag := True;
    end;
  end;
  if flag then
    Result := y
  else
    raise EListError.Create('source is empty');
end;

代码基本上是来自Enumerable.Max<T>的.Net System.Linq扩展方法的端口。您可以像在Nicks示例中一样使用它。

对于那些对二进制大小感兴趣的人来说很有趣:链接器能够删除从未使用过的方法。