4

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

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

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

4

4 回答 4

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)因为当在空列表上调用该方法时,我们无法提出与 I raise an exception 的通用等价物。

输出是:

12
 1.20000000000000E+0001
沃伦 P
于 2013-01-03T15:10:09.603 回答
8

这是一个替代答案:使用Spring.Collections.pasSpring4D 框架中的单元:(可在此处找到: 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. 
于 2013-01-06T04:13:01.127 回答
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;
于 2013-01-03T13:25:33.477 回答
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;

该代码基本上是 .NetEnumerable.Max<T>扩展方法的一个端口,来自System.Linq. 您可以像在尼克斯示例中一样使用它。

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

于 2013-01-18T11:59:34.907 回答