优雅的分支(任何语言)

时间:2014-03-23 20:47:18

标签: java syntax branch conventions

我只是编程了一段时间,还没有找到一种方法来编写分支代码,涵盖两个或更多布尔值的每个可能配置,而没有任何冗余的if语句。

例如,显示所有可能结果的表格可能如下所示:

          true    false
      ---------------------
true  | Thing A | Thing B |
      ---------------------
false | Thing C | Thing D |
      ---------------------

然而,我能想到的唯一能编程A但D的代码如下:

if(boolean1) {
    if(boolean2)
        ThingA();
    else
        ThingB();
}
else if (boolean2)
    ThingC();
else
    ThingD();

有没有办法写这个而不必为boolean2写两次检查?我知道只有一个检查可以运行一次这个代码的迭代,但是在需要担心的布尔值超过两个的情况下,这种方法可能变得非常麻烦。

3 个答案:

答案 0 :(得分:2)

如果您的目标是消除if语句,那么指向函数的4条目查找表将是您最优雅的答案;将您的两位(布尔值)合并为一个2位值,并使用它来确定要使用的查找表条目,即在pseuodocode中:

static FunctionArrayInYourLanguage fnAr[4] {ThingA(), ThingB(), ThingC(), ThingD()}

UnsignedIntegerType manyBooleans = (boolean1 LeftShift 1) BitwiseOR boolean2
Remark: Or any other way of combining your booleans, like casting a struct of 8 bits as a uint8_t in C or vice versa

Execute fnAr[manyBooleans]();

请注意,如果您能够负担查找表空间,这种技术可以扩展到多于2个布尔值,如果您真的为每个可能的组合提供了一个函数,那么您绝对可以负担得起这个空间。

答案 1 :(得分:1)

你可以做的是使用位移创建一个掩码并引入一个开关

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstdint>

using namespace std;

int main() {
  bool bArray[2];
  for (size_t i = 0 ; i < 2 ; i++) {
    cin >> bArray[i];
  }

  uint32_t mask = 0;

  mask = bArray[0];
  mask = mask << 1;
  mask = mask ^ bArray[1];

  switch(mask) {
    case 0:
      cout << "bot false" << endl;
      break;
    case 1:
      cout << "first false, second true" << endl;
      break;
    case 2:
      cout << "first true, second false" << endl;
      break;
    case 3:
      cout << "both true" << endl;
      break;
  }
  return 0;
}

你可以使用新的C ++ 11扩展使它非常优雅,你可以在其中重载文字运算符“”_和替换案例2:使用“10”_bin2int,其方式与在

中创建哈希的方式类似

Compile time string hashing

这里有一个完整的工作示例

http://dev.krzaq.cc/switch-on-strings-with-c11/

使用上面的信息,我能想到的最优雅的解决方案就像这样。请注意如何在编译时评估文字。你需要一个支持字符串文字的编译器来编译这个

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstdint>

using namespace std;

constexpr uint32_t basis = 0;

constexpr uint32_t bin2int_compile_time(char const* str,
                                        uint32_t last_value = basis) {
  return *str ?
    bin2int_compile_time(str+1,(last_value << 1) ^ ((uint8_t)*str)-48) :
    last_value;
}

constexpr uint32_t operator "" _bin2int(char const* p, size_t) {
  return bin2int_compile_time(p);
}

uint32_t bool2int(const bool* bools, const size_t length) {
  uint32_t mask = bools[0];
  for (size_t i = 1 ; i < length ; i++) {
    mask = mask << 1;
    mask = mask ^ bools[i];
  }
  return mask;
}

int main() {
  const size_t nBooleans = 2;
  bool bArray[nBooleans];
  for (size_t i = 0 ; i < nBooleans ; i++) {
    cin >> bArray[i];
  }

  uint32_t mask = bool2int(bArray, nBooleans);

  switch(mask) {
    case "00"_bin2int:
      cout << "both false" << endl;
      break;
    case "01"_bin2int:
      cout << "first false, second true" << endl;
      break;
    case "10"_bin2int:
      cout << "first true, second false" << endl;
      break;
    case "11"_bin2int:
      cout << "both true" << endl;
      break;
    default:
      break;
  }
  return 0;
}

答案 2 :(得分:0)

有面向对象的方法。

public interface Branch {
    public boolean isCondition();
    public void execute();
}

public class FirstThing implements Branch {

    private boolean boolean1;
    private boolean boolean2;

    public FirstThing(boolean boolean1, boolean boolean2) {
        this.boolean1 = boolean1;
        this.boolean2 = boolean2;
    }

    @Override
    public boolean isCondition() {
        return boolean1 & boolean2;
    }

    @Override
    public void execute() {
        thing00();      
    }

}

等表项的其余部分。

将每个实现类的实例添加到List。循环遍历列表,直到isCondition()为真,然后执行()。