有效地将整数与Delphi中的静态整数列表进行比较?

问题描述 投票:3回答:3

类似于any way to compare an integer variable to a list of integers in if statement,但在Delphi中,我如何测试整数(是否为consts的列表)的静态“列表”(宽松地说,是预定义的集合)中是否包含整数变量,或if语句中的显式值列表?

现在我会做这样的事情:

if (x = 1) or
   (x = 2263) or
   (x = 263553) or
   (x = whatever_int) then
begin
  //do something;
end;

但是我试图避免条件的冗长序列。

我正在使用Delphi XE6,所以如果有一些新的方法可以干净地实现这一目标,请告诉我。

delphi delphi-xe6
3个回答
4
投票

您当前的方法很好。编译器将产生有效的代码。如果效率是最重要的,则可以选择比较的顺序,以便首先检查最常用的值。这需要了解您的输入数据的分布。

另一种语法方法是case语句。例如:

case x of
1, 2263, 263553, whatever_int:
  // do other stuff
end;

[这会导致与if语句相似(实际上我怀疑是相同的)代码。但这也许更简洁,更容易阅读。在某些情况下,编译器能够生成跳转表。

如果效率对您至关重要,请确保检查编译器发出的代码,以获取发行版编译器选项,并执行性能分析。

我确实想知道您所说的高效到底是什么意思。在编程中,该术语具有与运行时性能有关的特定含义。但是我想知道您是否实际上更关心编写清晰简洁的代码,在这种情况下,高效是错误的说法。您的问题涉及避免重复使用or运算符,这一事实使我怀疑效率对您而言很重要。

另一方面,如果运行时性能很重要,则可以考虑放弃代码清晰度并实现索引跳转表。但是,在未先确定代码是瓶颈并分析您所做的任何更改之前,切勿对代码进行优化。


1
投票

您可以通过编写一些小函数使代码更清晰易读:

//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:像这样微调优化时一如既往:

  1. 使用配置文件在这里确认是否需要它。
  2. 使用配置文件来确认您是否获得了期望的收益。

0
投票

给定用例,我将使用TList<Integer>和方法:

  • procedure AddRange(const Values: array of T);
  • Contains(const Value: T): Boolean;
© www.soinside.com 2019 - 2024. All rights reserved.