Как проще всего получить максимальное значение в TList<Integer>
?
function GetMaximum(AList: TList<Integer>): Integer;
begin
Assert(AList.Count > 0);
Result := ?;
end;
Я читал, что в C # есть AList.Max
, есть ли что-то подобное в Delphi?
Как проще всего получить максимальное значение в TList<Integer>
?
function GetMaximum(AList: TList<Integer>): Integer;
begin
Assert(AList.Count > 0);
Result := ?;
end;
Я читал, что в C # есть AList.Max
, есть ли что-то подобное в Delphi?
Вот забавный пример реализации 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
Вот альтернативный ответ: используйте модуль Spring.Collections.pas
из фреймворка Spring4D: (находится здесь: 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.
ENumerable<T>
, поскольку это не проблема TList<T>
.
- person Jeroen Wiert Pluimers; 06.01.2013
IList
выставляет IEnumerable<T>
. В этом суть ответа Ника.
- person Jeroen Wiert Pluimers; 07.01.2013
IEnumerable<Integer>.Max
обрабатывает пустой контейнер?
- person David Heffernan; 07.01.2013
Использование 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;
IEnumerable
в .net? Другими словами, не могли бы вы сделать общую реализацию GetMaximum, используя обобщения / черты?
- person Warren P; 03.01.2013
Я согласен с тем, что использование коллекций 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;
Код в основном является портом метода расширения .Net Enumerable.Max<T>
из System.Linq
. Вы можете использовать его так же, как в примере Nicks.
Интересная вещь для тех, кого интересует их размер двоичного файла: компоновщик может удалять методы, которые никогда не используются.