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

时间:2015-05-13 10:47:08

标签: delphi delphi-xe6

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,所以如果有新的东西以干净的方式实现这一点,请告诉我。

4 个答案:

答案 0 :(得分:3)

您目前的做法很好。编译器将生成有效的代码。如果效率至关重要,那么您可以选择比较的顺序,以便首先检查最常见的值。这需要了解输入数据的分布。

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

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

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

如果效率对您至关重要,那么请确保检查编译器发出的代码,发布编译器选项以及执行分析。

我确实想知道你的意思是什么才能有效率。在编程中,该术语具有与运行时性能相关的特定含义。但我想知道你是否真的更关心编写清晰简洁的代码,在这种情况下,有效的是错误的术语。您的问题涉及避免重复or运算符这一事实让我怀疑效率对您来说至关重要。

另一方面,如果运行时性能是重要的,那么考虑放弃代码清晰度并实现索引跳转表。但是,如果不首先确定代码是瓶颈,并分析您所做的任何更改,就不要优化代码。

答案 1 :(得分: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. 使用分析确认您是否获得了预期的利益。

答案 2 :(得分:1)

鉴于用例,我将使用TList<Integer>及其方法:

  • procedure AddRange(const Values: array of T);
  • Contains(const Value: T): Boolean;

答案 3 :(得分:0)

为什么不简单:

x : integer;
begin
  if x in [1,2,5] then
  begin
    showmessage('x in 1,2,5');
  end;
end;