有效地将整数与 Delphi 中的静态整数列表进行比较?
Efficiently compare an integer against a static list of integers in Delphi?
与any way to compare an integer variable to a list of integers in if statement类似,但在Delphi中,我如何测试整数变量是否包含在整数的静态"list"(松散地说-预定义的集合)中(可能是 consts 的列表,或 显式值 的列表)在 if 语句中?
现在我会做这样的事情:
if (x = 1) or
(x = 2263) or
(x = 263553) or
(x = whatever_int) then
begin
//do something;
end;
但我正在努力避免 或 条件的冗长序列。
我正在使用 Delphi XE6,所以如果有新的东西可以干净地实现这一点,请告诉我。
你现在的做法很好。编译器将产生高效的代码。如果效率最重要,那么您可以选择比较顺序,以便首先检查最常见的值。这需要了解输入数据的分布。
另一种语法方法是 case
语句。例如:
case x of
1, 2263, 263553, whatever_int:
// do other stuff
end;
这导致与 if
语句类似(实际上我怀疑是相同的)代码。但它可能更简洁,更易于阅读。在某些情况下,编译器能够产生跳转 table。
如果效率对您来说至关重要,那么请务必检查编译器发出的代码、发布编译器选项并执行分析。
我确实想知道您所说的高效到底是什么意思。在编程中,该术语具有与运行时性能相关的特定含义。但我想知道你是否真的更关心编写清晰简洁的代码,在这种情况下高效是错误的术语。你的问题谈到避免重复 or
运营商这一事实让我怀疑效率对你来说很重要。
另一方面,如果运行时性能很重要,那么考虑放弃代码清晰度并实现索引跳转 table。但是,在没有首先确定它是瓶颈并分析您所做的任何更改之前,永远不要优化代码。
您可以通过编写一个小函数使代码更清晰易读:
//NOTE: This function is written in a way that would be compatible with any version of Delphi.
//Since you're using XE6, there are some improvement options available to you:
// E.g. You can make the function inline, use "for in", use a record helper, use generics
function ContainsInteger(const AValue: Integer; const AArray: array of Integer): Boolean;
var
I: Integer;
begin
Result := False;
for I := Low(AArray) to High(AArray) do
begin
if (AArray[I] = AValue) then
begin
Result := True;
Exit;
end;
end;
end;
现在您可以按如下方式调用您的函数:
if ContainsInteger(x, [1, 2263, 263553, whatever_int]) then
begin
//do something;
end;
注意:这会比 David 的回答中描述的 case 语句慢,但对于更长的数字列表,它有可能明显更快。
如果此函数可能会经常用于较长的列表:
- 您可以指定输入数组按升序排列的要求。 (否则行为将未定义。)
- 并修改函数进行二分查找
- 然后例如,一个包含 32 个数字的列表最多需要 5 次比较才能使用二进制搜索找到匹配项;而 case 语句需要平均 16。
NB:像往常一样微调优化时:
- 在这里使用profiling确认是否需要。
- 使用分析来确认您是否获得了预期的收益。
鉴于用例,我会使用 TList<Integer>
,其方法:
procedure AddRange(const Values: array of T);
Contains(const Value: T): Boolean;
为什么不简单:
x : integer;
begin
if x in [1,2,5] then
begin
showmessage('x in 1,2,5');
end;
end;
与any way to compare an integer variable to a list of integers in if statement类似,但在Delphi中,我如何测试整数变量是否包含在整数的静态"list"(松散地说-预定义的集合)中(可能是 consts 的列表,或 显式值 的列表)在 if 语句中?
现在我会做这样的事情:
if (x = 1) or
(x = 2263) or
(x = 263553) or
(x = whatever_int) then
begin
//do something;
end;
但我正在努力避免 或 条件的冗长序列。
我正在使用 Delphi XE6,所以如果有新的东西可以干净地实现这一点,请告诉我。
你现在的做法很好。编译器将产生高效的代码。如果效率最重要,那么您可以选择比较顺序,以便首先检查最常见的值。这需要了解输入数据的分布。
另一种语法方法是 case
语句。例如:
case x of
1, 2263, 263553, whatever_int:
// do other stuff
end;
这导致与 if
语句类似(实际上我怀疑是相同的)代码。但它可能更简洁,更易于阅读。在某些情况下,编译器能够产生跳转 table。
如果效率对您来说至关重要,那么请务必检查编译器发出的代码、发布编译器选项并执行分析。
我确实想知道您所说的高效到底是什么意思。在编程中,该术语具有与运行时性能相关的特定含义。但我想知道你是否真的更关心编写清晰简洁的代码,在这种情况下高效是错误的术语。你的问题谈到避免重复 or
运营商这一事实让我怀疑效率对你来说很重要。
另一方面,如果运行时性能很重要,那么考虑放弃代码清晰度并实现索引跳转 table。但是,在没有首先确定它是瓶颈并分析您所做的任何更改之前,永远不要优化代码。
您可以通过编写一个小函数使代码更清晰易读:
//NOTE: This function is written in a way that would be compatible with any version of Delphi.
//Since you're using XE6, there are some improvement options available to you:
// E.g. You can make the function inline, use "for in", use a record helper, use generics
function ContainsInteger(const AValue: Integer; const AArray: array of Integer): Boolean;
var
I: Integer;
begin
Result := False;
for I := Low(AArray) to High(AArray) do
begin
if (AArray[I] = AValue) then
begin
Result := True;
Exit;
end;
end;
end;
现在您可以按如下方式调用您的函数:
if ContainsInteger(x, [1, 2263, 263553, whatever_int]) then
begin
//do something;
end;
注意:这会比 David 的回答中描述的 case 语句慢,但对于更长的数字列表,它有可能明显更快。
如果此函数可能会经常用于较长的列表:
- 您可以指定输入数组按升序排列的要求。 (否则行为将未定义。)
- 并修改函数进行二分查找
- 然后例如,一个包含 32 个数字的列表最多需要 5 次比较才能使用二进制搜索找到匹配项;而 case 语句需要平均 16。
NB:像往常一样微调优化时:
- 在这里使用profiling确认是否需要。
- 使用分析来确认您是否获得了预期的收益。
鉴于用例,我会使用 TList<Integer>
,其方法:
procedure AddRange(const Values: array of T);
Contains(const Value: T): Boolean;
为什么不简单:
x : integer;
begin
if x in [1,2,5] then
begin
showmessage('x in 1,2,5');
end;
end;