重构 if-else-if 结构
Refactor if-else-if structure
如何重构以下C++代码?我在程序中使用 C++11
void f(int a, int b, int c, int d, int e, int f) {
// MAX1..MAX6 are constants, N1..N6 are constants
if( a > MAX1) {
.. code block 1..
}
else if(b > MAX2) {
.. code block 2..
}
else if(c > MAX3) {
.. code block ..
}
else if(d > MAX4) {
.. code block 3 ..
}
else if(e > MAX5) {
.. code block 4 ..
}
else if(f > MAX6) {
.. code block5 ..
}
else if(( a > N1) && ( b > N2)) {
.. code block 6 ..
}
else if(( c > N3) && ( d > N4)) {
.. code block 7 ..
}
else if (( e > N5) && ( f > N6)) {
.. code block 8 ..
}
else if (( a > N1) && ( b > N2) && (d > N4)) {
.. code block 9 ..
}
else if (..some combination of (a > N1) to (f > N6)...) {
// there are more than 30 such combinations in my code
.. code block XX ..
}
else {
.... code block ....
}
函数中最多有 64 个代码块,每个代码块都可以使用匿名函数或命名函数:
my_func_array[64] = {
[CONDITION(1,0,0,0,0,0)] = { codeblock1 },
[CONDITION(0,1,0,0,0,0)] = { codeblock2 },
...
};
宏基本上会将前 6 个输入连接到索引,基本上转换为:
my_func_array[64] = {
[32] = { ... },
[16] = { ... },
};
这意味着您不必以任何特定顺序输入条件...
运行时,您还必须评估所有条件:
int condition = CONDITION(a < MAX1, b < MAX2, c < MAX2, ...);
if (my_func_array[condition])
my_func_array[condition]();
else
{
// this second block should cover all the other cases
int condition2 = CONDITION(a < N1, b < N2, c < N3, ... );
if (my_func_array2[condition2])
my_func_array2[condition2]();
}
你所拥有的似乎不是不合理的,但如果你真的想重构,你可以创建一个枚举
枚举类 CaseSelect {CASE0, CASE1, CASE2};
然后创建一个看起来与当前 if 树非常相似的函数,每个代码块返回相应的枚举。
然后使用枚举创建一个 case 语句,每个枚举中都有适当的逻辑
它不会给你带来太多好处,但它将选择状态的逻辑与操作逻辑分开,这在多行语句的情况下可能对清晰度有所帮助
您当然可以从a
f
、MAX
和N
数组开始(只是一个起始草图,我可以用有关您的条件、代码块和用途的更多信息进行扩展):
const int MAX[6] = { ... };
const int N[6] = { ... };
const std::function funcs[6];
void f(int in[6])
{
for(int i = 0; i < 6; ++i)
{
if(in[i] > MAX[i])
{
funcs[i]();
break;
}
}
}
假设您有一个互斥整数范围(xi到yi)的离散数N,并且您想根据给定输入z的范围调用一些代码块,那么:
- 您希望使用
std::map
二叉树来存储每个范围的开头和相应的 Lambda。 - 调用 Z 上的
std::lower_bound
以查找候选范围 - 然后对照 Z 检查该范围的上限。
- 如果在里面,调用 lambda
这将给出 O(log(N)) 时间,而大 if-else 链的 O(n) 时间。
首先,我会按照 Mark B 的建议去掉前 6 个分支,但是
-
而不是
break
我会return
, -
我会简单地使用函数指针,
std::function
是矫枉过正这里 -
我会使用
std::array
和绑定检查而不是原始数组。
现在无聊的情况已经消失了,我会对剩余的分支应用相同的模式,但这需要一些技巧,因为这些条件是复合的。
我假设MAX1 > N1
.我希望这是真的。
首先,我将构建一个十进制数,对所有参数进行编码:
int arg=10^5*(a>N1?1:0)+10^4*(b>N2?1:0)+10^3*(c>N3?1:0)+10^2*(d>N4?1:0)+10*(e>N5?1:0)+(f>N1?1:0)
我也会以类似的方式对条件进行编码。例如:条件(a > N1) && ( b > N2)
变为arg >= 110000
,等等。
如您所见,在此编码之后,您可以像前 6 个分支一样消除剩余的分支。
如果效率是一个主要问题,你可以用 2 的幂(位移,然后使用位掩码)做同样的技巧。我不做一些摆弄,所以我不能帮你,但它的工作方式相同,效率更高。可能和拥有那么长的if-else if链你现在拥有的东西一样有效,或者甚至可能更有效,因为你没有重复相同的比较。
希望这有帮助。
如果有很多规则,函数对象(例如:lambdas)可以在那里进行救援:
出于演示目的,我对其进行了一点简化,只有 3 个参数......
而且我认为非检查有一个安全值,在这种情况下,0
(没有它可能会生活,但那样它看起来会更丑)。
#include <iostream>
#include <functional>
struct Rule {
int a;
int b;
int c;
std::function<int()> fun;
};
Rule rules[]{
{ 10, 0, 0, []() { std::cout << "First!"; return 0;} },
{ 0, 20, 0, []() { std::cout << "Second!"; return 1;} }
};
int f(int a, int b, int c) {
for (Rule rule : rules) {
if ((rule.a == 0 || a > rule.a)
&& (rule.b == 0 || b > rule.b)
&& (rule.c == 0 || c > rule.c))
return rule.fun();
}
std::cout << "Not match!";
return 2;
}
int main() {
f(5, 23, 3);
};
- 在 C++ 中的 if-else if- else 语句期间更改变量
- 使用 if/else if 的函数输出问题
- MQL4:我的if/else if liop只有一半导致当前执行
- if else-if else 语句 c++ 的替代项
- 优化代码/实现"for"循环而不是长"if - else if - else"
- if else-if梯形图和编译器优化
- 涉及函数和 if/else if 语句的类
- 重构 if-else-if 结构
- 可执行文件C++问题:while 循环和 if/else if/else
- C++if/else-if语句工作不正常
- C++中的基本If/Else If
- 如何将一系列if/else-if/else-if/关系链转换为线性循环代码
- C++,将if/else-if更改为switch语句
- C++ 在 if/else if 中启动不同的文件
- If/else If总是转到else语句
- 通过hash_map<字符串 fnPtr>调用函数指针是否比C++中的多个 if/else if/else 语句更有效或更好?
- if/else if/else电话账单计算器
- "if if"与"if else if"的性能差异
- 如何重构这个结构,if-else-if-else-if * 100
- c++中if else if语句的问题