用JavaScript实现复杂的决策表
下面是JavaScript专家的一个实现细节问题 我有一个包含许多字段的UI,其中字段的值以一种复杂的方式依赖于七位输入的值。当用户看到更多应用程序时,可能会定期更改的128个值中的任何一个值的确切显示内容是什么 现在,我已经通过if-then-else梳将其实现为一个决策树,但是在需求变化的情况下,它很脆弱,很难正确实现 我考虑过的一种实现方法是创建一个从0x0到0x7F的值数组,然后在每个位置存储一个闭包-- 然后用用JavaScript实现复杂的决策表,javascript,Javascript,下面是JavaScript专家的一个实现细节问题 我有一个包含许多字段的UI,其中字段的值以一种复杂的方式依赖于七位输入的值。当用户看到更多应用程序时,可能会定期更改的128个值中的任何一个值的确切显示内容是什么 现在,我已经通过if-then-else梳将其实现为一个决策树,但是在需求变化的情况下,它很脆弱,很难正确实现 我考虑过的一种实现方法是创建一个从0x0到0x7F的值数组,然后在每个位置存储一个闭包-- 然后用 tbl[bitsIn](); 这至少让决策逻辑变成了一堆任务 问题:有更
tbl[bitsIn]();
这至少让决策逻辑变成了一堆任务
问题:有更好的办法吗
(更新:天哪,那句关于“ajax iphone标签”的话是怎么出现的?难怪有点令人费解。)
更新
发生了什么事?基本上,我选择了第四个选项,尽管与我所选择的类似。逻辑非常复杂,我最终构建了一个Python程序,在服务器中生成一个真值表(生成代码,实际上,主机是一个应用程序),并将决策逻辑完全移动到服务器中。现在JavaScript端只是解释一个JSON对象,其中包含各个字段的值
最终,这可能会再经过一次迭代,并成为数据库表中的数据,通过位向量进行索引
桌子驱动的部分肯定是未来的发展方向;显示器的具体要求已经有六个新的变化。由于情况(如您所述)如此不规则,似乎没有更好的方法。不过,我可以建议你改进一下跳台。你提到你有错误和重复。因此,您可以将它们指定给命名函数,而不是显式地将它们指定给闭包,这样就不必复制显式闭包
var doAThingAndAnother = function (){ doAThing(); doAnotherThing(); }
var tbl; // initialize it with the values
...
tbl[0x42] = doAThingAndAnother;
tbl[0x43] = doAThingAndAnother;
虽然没有多大进步,但这是我唯一能想到的!你似乎已经涵盖了大部分其他问题。由于需求变化如此之大,我认为您可能不得不放弃优雅,而设计得不那么优雅,但仍然很容易改变。我看到两种选择
两种解决方案的共同点是以下命名函数:
function aThing() {}
function anotherThing() {}
function aThirdThing() {}
道岔
function exec(bits) {
switch(bits) {
case 0x00: aThing(); anotherThing(); break;
case 0x01: aThing(); anotherThing(); aThirdThing(); break;
case 0x02: aThing(); aThirdThing(); break;
case 0x03: anotherThing(); aThirdThing(); break;
...
case 0x42: aThirdThing(); break;
...
case 0x7f: ... break;
default: throw 'There is only 128 options :P';
}
}
地图之路
function exec(bits) {
var actions = map[bits];
for(var i=0, action; action=actions[i]; i++)
action();
}
var map = {
0x00: [aThing, anotherThing],
0x01: [aThing, anotherThing, aThirdThing],
0x02: [aThing, aThirdThing],
0x03: [anotherThing, aThirdThing],
...
0x42: [aThirdThing],
...
};
在这两种情况下,你都会打电话
exec(0x42);
您是否考虑过在服务器上生成决策树而不是手工编写?使用任何干净、易于使用的表示,然后修改并编译为丑陋但高效的javascript,用于客户端 决策树很容易表示为数据,并且作为传统的树数据结构很容易理解和使用。你可以用任何对你有意义的形式来储存这棵树。作为数据验证和修改它也应该是直接的
然后,当您需要使用决策树时,只需将其编译/序列化为一个大的JavaScript,如果else、switch或hash混乱的话。这也应该是相当直接的,可能比试图维护一个包含数百个元素的
开关要容易得多。如果您想看一下,我有一个JavaScript决策树工具的粗略示例:
从我对您的问题的理解来看,您的重构思想是合理的,但从您的描述来看,我不确定您需要什么:PDO每一位都决定一个特定的操作?如果是这样,为什么不对[0x01、0x02、0x04、0x08、0x10、0x20、0x40]的值执行按位AND运算呢?@Martin,关键是是否有比我的lambdas表更灵活的方法来执行此操作。@draeton,这是一个好的观点。该表实际上是稀疏的(许多值只是无效的,表示错误,但不规则地)和冗余的(多个值可能附加了相同的操作,但又没有规则性)。如果这种关系是固定的,我可以将其转换为FSA,但我已经尝试过了,需求变化破坏了FSA。出于好奇,你决定了什么?您找到更好的解决方案了吗?该循环不能是(操作中的var action)action()的代码>?它可以,但没有什么意义。本例中的操作是一个函数引用数组,您不希望使用for(数组中的var i)在数组上循环,因为这样做速度要慢得多,而且会在不同浏览器中产生不均匀的结果。某些浏览器将数组上的“length”属性视为对象的另一个成员,并提供该属性以及函数引用。[].PropertySiEnumerable('length')==false
exec(0x42);