で最大値を取得する最も簡単な方法は何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 ウォーレン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.
使用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;
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.