【问题标题】:Evaluate multiple boolean conditions exclusively, only one can be true (Delphi)独占评估多个布尔条件,只有一个为真(Delphi)
【发布时间】:2015-05-10 00:59:31
【问题描述】:

我有一个函数,它可以评估多个(在我的情况下为 7 个)布尔变量和条件,如果其中只有一个为真(当然其余为假),则结果为真。我有以下代码:

function GetExclusiveTrue: boolean;
begin
  Result:= (
    Integer(BoolVar1) + 
    Integer(BoolVar2) + 
    Integer(BoolFunc3) + 
    Integer(BoolVar4) + 
    Integer(BoolFunc5) + 
    Integer(BoolVar6) + 
    Integer(BoolVar7)) = 1;
end;

我只是想知道是否有比这更好的解决方案?

PS:我想我没有正确定义我的问题。

我正在寻找仅使用逻辑运算符的解决方案,不涉及任何强制转换。

PS2:看起来我无法正确解释我在寻找什么。我想看到一个没有迭代、选择、函数调用等的解决方案。只允许布尔运算符。为什么?我只是想知道这是否可能。寻找与上述函数提供相同结果的逻辑运算组合。

【问题讨论】:

  • 我很好奇,您要解决的真正问题是什么?为什么只允许使用逻辑运算符?为什么不允许强制转换或位操作?它必须是纯德尔福吗?你如何量化“更好”?
  • 当我说得更好时,我指的只是逻辑运算符。我不需要使用强制转换和按位运算符的解决方案,如您所见,我已经使用类型强制解决了该任务,我也可以使用按位运算符解决它。这是一个理论问题。是的,必须用 Delphi 编写。
  • FWIW,而不是铸造你会使用ord()

标签: delphi boolean operand


【解决方案1】:

我想看到一个没有迭代、选择、函数调用等的解决方案。只允许布尔运算符。为什么?我只是想知道这是否可能。寻找与上述函数提供相同结果的逻辑运算组合。

您希望仅使用逻辑 andorxornot 运算符来实现此目的。是这样的:

Result :=
     (b1 and not (b2 or b3 or b4))
  or (b2 and not (b1 or b3 or b4))
  or (b3 and not (b1 or b2 or b4))
  or (b4 and not (b1 or b2 or b3));

我举了一个只有四个布尔值的例子,但任何数字的概念都是相同的。

【讨论】:

  • 如果我理解正确,我必须针对其余的逻辑操作数测试每个逻辑操作数。对吗?
  • 除此之外,我看不到任何其他方式来满足您的限制。有变种,但它们都是这种基本形式。例如,您可以将第一行写为b1 and not b2 and not b3 and not b4。但是,如果您只能使用逻辑运算符,那么就剩下这些了。
  • 好的,您的解决方案符合我的问题要求。
  • @tcxbalage 这似乎是唯一的解决方案,也是正确的解决方案,可以回答您的问题。
【解决方案2】:

这是一个计算 only-1-true 的函数,而不考虑要检查的布尔值的数量:

function GetExclusiveTrue(boolarray: array of Boolean) : Boolean;
var
  arrayindex  : integer;
begin
  result := false;
  for arrayindex := 0 to high(boolarray) do
    if boolarray[arrayindex] then
    begin
      result := not result;
     if not result then exit;
    end;
end;

首先,假设false 结果,然后扫描提供的数组。在找到的第一个 true(如果有)上设置返回值 true,如果找到第二个 true,则清除返回值并退出。

这是计算有多少是真的的特殊情况:

function howmanytrue(boolarray: array of Boolean) : integer;
var
  arrayindex  : integer;
begin
  result := 0;
  for arrayindex := 0 to high(boolarray) do
    if boolarray[arrayindex] then inc(result);
end;

显然,GetExclusiveTrue = howmanyaretrue([your Booleans]) = 1 但这允许其他问题,例如 are none/all/all-but-1/majority/at-least-3/no-more-than-2/exactly-half true(假设您知道要检查的布尔值的数量。)

我用一组 11 个复选框和 2 个面板对此进行了测试

procedure TForm1.CheckBoxClick(Sender: TObject);
begin
  Panel1.Caption := BoolToStr(GetExclusiveTrue([checkbox1.Checked,checkbox2.Checked,checkbox3.Checked,checkbox4.Checked,checkbox5.Checked,checkbox6.Checked,checkbox7.Checked,checkbox8.Checked,checkbox9.Checked,checkbox10.Checked,checkbox11.Checked]),true);
  Panel2.Caption := IntToStr(howmanytrue([checkbox1.Checked,checkbox2.Checked,checkbox3.Checked,checkbox4.Checked,checkbox5.Checked,checkbox6.Checked,checkbox7.Checked,checkbox8.Checked,checkbox9.Checked,checkbox10.Checked,checkbox11.Checked]));
end;

【讨论】:

    【解决方案3】:

    如果你不想投射,那么你可以通过这种方式达到同样的效果:

    function GetExclusiveTrue: boolean;
    var
      Count: Integer;
    begin
      Count := 0;
      if BoolVar1 then
        Inc(Count);
      if BoolVar2 then
        Inc(Count);
      if BoolFunc3 then
        Inc(Count);
      if BoolVar4 then
        Inc(Count);
      if BoolFunc5 then
        Inc(Count);
      if BoolVar6 then
        Inc(Count);
      if BoolVar7 then
        Inc(Count);
      Result := (Count = 1);
    end;
    

    【讨论】:

    • 这与类型转换做同样的事情,只是使用了两倍的代码行数。
    • 我知道,但 OP 想要“仅逻辑运算符,不涉及任何强制转换”。无论如何,如果你将每个“if”折叠成一行,那么它只会长几行:-)
    • 将其折叠成单行只会使其更难阅读;它实际上并没有减少代码量。与OP使用的方式相比,我认为这样做没有任何好处;他们正在完成同样的事情——添加整数值并测试总和是否等于 1。我没有说你错了,我也没有投反对票;只是提到它。
    • 我从来没有说过这是一个更好的解决方案。我只是按照被问到的方式回答这个问题。
    • 嗯,问题是明确要求比现有解决方案“更好的解决方案”。
    【解决方案4】:

    一个更好的解决方案可能是,你做一个开放的数组

    function GetExclusiveTrue(Values: array of Boolean ): Boolean;
    

    并通过迭代求和。

    【讨论】:

    • 我不会称这是一个“更好”的解决方案——我认为 OP 已经在使用这两个选项中更好的一个。
    • 伙计,第一个数组就是为此而存在的,在 Delphi 中,布尔类型是枚举,如果函数的结果是布尔值,则不能转换为整数。我认为通过这种方式编写代码不是一个好习惯,如果您需要更多变量后,您将重复代码。
    • 我明白你的意思,但是条件的数量在运行时间上没有变化。您的解决方案更加自动化,但我的问题是强制转换,而不是仅使用布尔操作数。我想我没有正确定义我的问题,我的错。
    • 我理解了这个问题 - 只有一个条件必须为真,如果多个条件为真,则返回假。对吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多