Delphi 如何在通用TList中获得最大值<;整数>;?
在Delphi 如何在通用TList中获得最大值<;整数>;?,delphi,delphi-xe2,Delphi,Delphi Xe2,在t列表中获取最大值的最简单方法是什么 函数GetMaximum(AList:TList):整数; 开始 断言(AList.Count>0); 结果:=?; 结束; 我读到C#有一个AList.Max,Delphi中有类似的东西吗?使用for。。在中: function GetMaximum(AList: TList<Integer>): Integer; var I: Integer begin Assert(AList.Count > 0); Result :
t列表中获取最大值的最简单方法是什么
函数GetMaximum(AList:TList):整数;
开始
断言(AList.Count>0);
结果:=?;
结束;
我读到C#有一个
AList.Max
,Delphi中有类似的东西吗?使用for。。在
中:
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;
函数GetMaximum(AList:TList):整数;
变量
I:整数
开始
断言(AList.Count>0);
结果:=低(整数);
因为我知道
如果我>结果,那么
结果:=I;
结束;
下面是一个有趣的示例,它在通用容器上实现了
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.
这里有一个替代答案:使用Spring4D框架中的
Spring.Collections.pas
单元:(可在此处找到:)
程序ListNumerableDemo;
{$APPTYPE控制台}
使用
System.SysUtils
春季系列;
变量
名单:IList;
可枚举:IEnumerable;
开始
尝试
列表:=TCollections.CreateList;
列表.AddRange([1,6,2,9,54,3,2,7,9,1]);
可枚举:=列表;
WriteLn(可枚举的最大值);
ReadLn;
除了
关于E:Exception-do
Writeln(E.ClassName,“:”,E.Message);
结束;
结束。
我同意使用Spring集合可能是最简单的方法。但是,可能有理由不使用它们(到处都在使用泛型集合)
下面是如何使用函数Max:T
创建一个扩展TEnumerable
的新类型
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;
类型
可枚举=记录
私有的
资料来源:微不足道;
公众的
函数Max:T;
类运算符隐式(常量值:TEnumerable):可枚举;
结束;
类运算符可枚举。隐式(
常量值:TEnumerable):可枚举;
开始
Result.source:=值;
结束;
函数可枚举。最大值:T;
变量
默认值:IComparer;
x、 y:T;
标志:布尔;
开始
如果未分配(源),则
引发eargumentnileexception.Create('Source');
默认值:=TComparer.default;
标志:=假;
对于源代码中的x
开始
如果旗子那么
开始
如果为默认值,则比较(x,y)>0,然后
y:=x;
结束
其他的
开始
y:=x;
标志:=真;
结束;
结束;
如果旗子那么
结果:=y
其他的
创建('源为空');
结束;
该代码基本上是System.Linq
中.NetEnumerable.Max
扩展方法的一个端口。您可以像在Nicks示例中一样使用它
对于那些对二进制大小感兴趣的人来说,有趣的事情是:链接器能够删除从未使用过的方法。NET方式:当然,.NET有可爱的扩展方法来做这类事情。……定义IEnumerable接口,提供类似LINQ的可枚举扩展方法。推荐@Marjan Venema:在泛型集合中,定义了TEnumerable类。另一方面,在Spring Delphi框架中,集合是基于接口的。在单元Spring.Collections.list中定义了一个类TList,它提供扩展方法,并最终实现IEnumerable(T)。例如,您可以调用List.Max,也可以调用List.Reversed。另请参见。@Marjan Venema:Nick Hodges还写了一系列关于依赖注入的优秀文章。你也有和。就像我说的:推荐!这可以用一种与.net中的
IEnumerable
功能相当的方式来实现吗?换句话说,你能使用泛型/特征为GetMaximum做一个泛型实现吗?@Warren--Spring.Collections.pas单元有IEnumerable,这将使它变得简单。+1,用于使用ENumerable
,因为它根本不是TList
问题。由于IList继承自IEnumerable,我们可以使用List.Max,而不必将其强制转换为IEnumerable:)@Jeroen我完全不理解这个评论。答案使用通用列表。只是不是Generics.Collections.Spring中的变体。在春季,不仅仅是IList
公开了IEnumerable
。这是尼克回答的关键。@David:问得好。我尝试了上面的演示,并注释掉了填充列表的AddRange。它做了我希望它能做的事。引发异常EInvalidOpException,并显示消息“此序列为空”
12
1.20000000000000E+0001
Warren P
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.
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;