是否可以优化这种(矩阵)算法:
// | case 1 | case 2 | case 3 | // ------|--------|--------|--------| // | | | | // case a| a1 | a2 | a3 | // | | | | // case b| b1 | b2 | b3 | // | | | | // case c| c1 | c2 | c3 | // | | | | switch (var) { case 1: switch (subvar) { case a: process a1; case b: process b1; case c: process c1; } case 2: switch (subvar) { case a: process a2; case b: process b2; case c: process c2; } case 3: switch (subvar) { case a: process a3; case b: process b3; case c: process c3; } }
代码相当简单,但你必须想象更复杂的"开关/案例".
我使用3个变量.根据他们取值1,2,3或a,b,c或alpha,beta,charlie有不同的过程来实现.是否可以通过一系列"开关/外壳"来优化它?
(问题已经在法语中提到了这里).
编辑 :(来自Dran Dane对以下评论的回答.这些也可能在这个更显着的位置!)
" 优化 "应理解为必须编写更少的代码,更少的"切换/案例".我们的想法是提高可读性,可维护性,而不是性能.
可能有一种方法可以通过"责任链"编写更少的代码,但是这个解决方案在所有方面都不是最优的,因为它需要在内存中创建许多对象.
听起来你想要的是一个'有限状态机',使用这些情况你可以激活不同的进程或'状态'.在C中,这通常使用函数指针的数组(矩阵)来完成.
所以你基本上创建一个数组并将正确的函数指针放在正确的标记上,然后使用'var'作为正确'process'的索引,然后你调用它.您可以在大多数语言中执行此操作.这样,机器的不同输入激活不同的过程并将其带到不同的状态.这对许多应用非常有用; 我自己一直在MCU开发中使用它.
编辑:Valya指出我可能应该展示一个基本模型:
stateMachine[var1][var2](); // calls the right 'process' for input var1, var2
因为这么多的回应取决于
有效目标("优化"是什么意思,嵌套交换机的不满意)
将要应用此构造的上下文(应用程序隐含的最终需求是什么)
TokenMacGuy明智地询问目标.我花时间检查问题及其在法国网站上的回复,我仍然对目标感到疑惑...... Dran Dane最近的回应似乎指向减少代码量/提高可读性但是让我们回顾一下:
处理速度:嵌套开关效率非常高,可能需要少于3次乘法才能获得映射表的索引,但可能不均匀.
可读性:是的可能是一个问题,随着变量和级别的增加,组合爆炸的数量增加,并且switch语句的格式也倾向于在长的垂直延伸上扩展分支点和相关值.在这种情况下,使用fct初始化3维(或更多)表.指针将分支值和要在单行上调用的函数放回原点.
写少量代码:对不起,这里帮助不大; 在一天结束时,我们需要考虑相对较多的组合,"地图",无论其形式如何,都必须写在某处.诸如TokenMacGuy之类的代码生成器可能会派上用场,在这种情况下看起来有点过分.发电机有它们的位置,但我不确定是这种情况.两种情况之一:如果变量和级别的数量足够小,那么生成器是不值得的(如果变量和级别的数量是变量,那么设置起来比创建实际代码要花费更多时间)重要的是,生成的代码难以阅读,难以维护...)
简而言之,我关于使代码更具可读性(并且编写速度更快)的建议是法国网站上描述的表/矩阵方法.
该解决方案分为两部分:
一次初始化三维阵列(3级); (或者如果愿意的话,可以使用"发烧友"的容器结构:例如树).这是通过以下代码完成的:
// This is positively more compact / readable ... FctMap[1][4][0] = fctAlphaOne; FctMap[1][4][1] = fctAlphaOne; .. FctMap[3][0][0] = fctBravoCharlie4; FctMap[3][0][1] = NULL; // impossible case FctMap[3][0][2] = fctBravoCharlie4; // note how the same fct may serve in mult. places
在需要调用函数的地方有一个相对简单的代码片段:
if (FctMap[cond1][cond2][cond3]) { retVal = FctMap[cond1][cond2][cond3](Arg1, Arg2); if (retVal < 0) DoSomething(); // anyway we're leveraging the common api to these fct not the switch alternative .... }
如果组合空间相对稀疏地填充(交换机"树"中的许多"分支"未被使用)或者某些功能需要不同的参数集,则可以提示不使用上述解决方案的情况是:对于这两种情况,我想首先插入一个Joel Goodwin首先提出的解决方案,它基本上将几个级别的各种键组合成一个更长的键(如果需要,还有分隔符),基本上将问题归结为一个长但单级的开关语句.
真正的讨论应该是为什么我们首先需要这样的映射/决策树.不幸的是,要回答这个问题需要了解底层应用程序的真实性质.可以肯定的是,我并不是说这表明设计不好.在某些应用程序中,一个大的调度部分可能有意义.但是,即使使用C语言(法语站点贡献者似乎不符合面向对象的设计),也可以采用面向对象的方法和模式.无论如何,我正在分歧......)应用程序可能总体上更好地服务于替代设计模式,其中"关于什么时候调用的信息树"已经分布在几个模块和/或几个对象中.
抱歉以相当抽象的方式谈论这个问题,只是缺乏应用程序细节......重点仍然是:挑战我们需要这个大型调度树的想法; 想一想整个应用程序的替代方法.
Alors,bonne机会!;-)