如何在 javascript 中实现决策树。寻找比我丑陋的更好的解决方案

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8368698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 03:13:15  来源:igfitidea点击:

How to implement a decision tree in javascript. Looking for a better solution than my ugly ones

javascriptlogicdecision-tree

提问by Dale

I'm looking for a better way to implement a decision tree in javascript. Being very new to programming I have a very limited number of tools in my toolbox. The only ways I know to do this are: .with a huge ugly hard to maintain and follow if else if statement .I could use a switch/case statement and do a state machine type thing.

我正在寻找一种更好的方法来在 javascript 中实现决策树。作为编程新手,我的工具箱中的工具数量非常有限。我知道这样做的唯一方法是: . 很难维护和遵循 if else if 语句。我可以使用 switch/case 语句并执行状态机类型的操作。

Suggestions and theories are appreciated. Also, small code examples would be very helpful. Thanks for taking a look.

建议和理论表示赞赏。此外,小的代码示例将非常有帮助。谢谢参观。

Dale

戴尔

回答by artistoex

If it is a really big tree, and especially if it is generated from data, you could treat the decision functions like data, using a functional approach. For example:

如果它是一棵非常大的树,特别是如果它是从数据生成的,则可以使用函数方法将决策函数视为数据。例如:

var decisionTree = 
    new Case( true, Array(
                  new Case ( function(n){ return n < 0; }, Math.sin ),
                  new Case ( function(n){ return n < 2; }, "0<= n < 2" ),
                  new Case ( true, "Greater than two " )));

decisionTree.evaluate(1); // evaluates to string "0<= n < 2"
decisionTree.evaluate(-Math.PI/2); // evaluates to -1
decisionTree.evaluate(5); // evaluates to string "Greater than two"

Using this implementation, you can arbitrarily nest your tree:

使用这个实现,你可以任意嵌套你的树:

// Represents a predicate and corresponding action to take if predicate is a
// match.
//
// predicate : true or Function( object ) returning a boolean.
//
// action : One of Function, Case, Array of Cases or other value (see
//          Case.evaluate as to how each is applied)
//
//
Case = function (predicate, action) {  
    this.predicate = predicate;
    this.action = action;
};


Case.prototype = {
    nomatch : { match : false },
    match : function (v) { return { match : true, result :v }; },


    // Recursively test Cases and applies corresponding action on
    // `object`.
    //
    // The action applied depends on the datatype of `action`:
    //
    // - Function : evaluates to `action( object )`
    // 
    // - Case : A subsequent test is performed.  Evaluates to whatever
    //          the Cases action evaluates to.
    //          
    // - Array of Cases : Subsequent tests are performed.  Evaluates to whatever
    //          the action of the first matching Case evaluates to.
    //
    // - Any other Value : Evaluates to itself
    // 
    // returns object containing fields:
    //
    //     match:  boolean, indicates if Case was a match
    //
    //     result:  result of action applied
    // 
    evaluate : function( object ) {
        var match = this.predicate;

        if ( match instanceof Function )
            match = match( object );

        if ( match ) {

            if (this.action instanceof Function )
                return this.match( this.action(object) );

            if ( this.action instanceof Case )
                return this.action.evaluate( object );

            if ( this.action instanceof Array ) {
                var decision;
                var result;
                for (var c = 0; c < this.action.length; c++ ) {
                    decision = this.action[c];
                    if ( decision instanceof Case )  {
                        result = decision.evaluate( object );
                        if (result.match)
                            return result;
                    } else throw("Array of Case expected");
                }

                return this.nomatch;
            }

            return this.match(this.action);
        } 
        return this.nomatch;
    }
};

回答by djhaskin987

The best practice for this sort of thing is to nest if-then statements in a meaningful way, and then put them in their own function bodies. A function should never have more than 2 nested if's; after that, it is acceptable to put further nested if's in functions which are named and implemented well, thus abstracting the complexity of the program while retaining its meaning for the programmer who will read your code after you're gone. :)

这种事情的最佳实践是以有意义的方式嵌套 if-then 语句,然后将它们放入自己的函数体中。一个函数不应有超过 2 个嵌套的 if;之后,可以在命名和实现良好的函数中进一步嵌套 if ,从而抽象程序的复杂性,同时保留其对在您离开后阅读您的代码的程序员的意义。:)