Jens Mühlenhoff
Jens Mühlenhoff

Reputation: 14873

How to get the maximum Value in a generic TList<Integer>?

What is the easiest way to get the maximum value in a TList<Integer>?

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

I read that C# has a AList.Max, is there something like that in Delphi?

Upvotes: 5

Views: 3482

Answers (4)

Stefan Glienke
Stefan Glienke

Reputation: 21748

I agree that using the Spring collections is probably the easiest way. However there may be reasons to not use them (already using Generics.Collections all over the place).

So here is how to make a new type that extends TEnumerable<T> with a 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;

The code is basically a port of the .Net Enumerable.Max<T> extension method from System.Linq. You can use it just like in Nicks example.

The interesting thing for those interested in their binary size: linker is able to remove the methods that are never used.

Upvotes: 1

Nick Hodges
Nick Hodges

Reputation: 17138

Here's an alternative answer: Use the Spring.Collections.pas unit from the Spring4D framework: (found here: 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. 

Upvotes: 9

David Heffernan
David Heffernan

Reputation: 613272

Here's a fun example with a MaxValue implementation on a generic container:

{$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.

Because we cannot come up with a generic equivalent to low(Integer) I raise an exception when the method is called on an empty list.

The output is:

12
 1.20000000000000E+0001
Warren P

Upvotes: 10

Jens M&#252;hlenhoff
Jens M&#252;hlenhoff

Reputation: 14873

Using 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;

Upvotes: 3

Related Questions