2011-12-03 1 views
7

나는 자바 스크립트에서 의사 결정 트리를 구현하는 더 좋은 방법을 찾고 있습니다. 매우 프로그래밍에 익숙하지 않기 때문에 도구 상자에 매우 제한된 수의 도구가 있습니다. 내가 이것을 알고있는 유일한 방법은 다음과 같다. . 엄청나게 유지하기가 어렵고 if else 문을 따라야한다. . switch/case 문을 사용하고 상태 시스템 유형을 수행 할 수있다.자바 스크립트에서 의사 결정 트리를 구현하는 방법. 내 추한 사람보다 더 나은 솔루션을 찾고

제안 및 이론을 높이 평가합니다. 또한, 작은 코드 예제는 매우 도움이 될 것입니다. 봐 주셔서 감사합니다. 자신의 기능을 몸에 넣어 경우 - 다음 문장 다음에 의미있는 방식으로에 등을

데일

+0

는 의사 결정 트리 다만 특별히 구조화 된 흐름도이다? – Dale

답변

10

정말 큰 트리이고 특히 데이터에서 생성 된 경우 기능적 접근 방식을 사용하여 데이터와 같은 의사 결정 기능을 처리 할 수 ​​있습니다. 예를 들면 :

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" 

이 구현을 사용하여 수행 할 수 있습니다 임의의 둥지 당신의 나무 :

// 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; 
    } 
}; 
+0

이것은 굉장합니다! 감사. 성능 관점에서 이에 대한 의견이 있으십니까? – Dale

+0

Amazing :) 나는 인터 프리터가 어떻게 최적화했는지 궁금하다. – Andrei

0

이런 종류의 물건에 대한 가장 좋은 방법은 둥지입니다. 함수는 두 개 이상의 중첩 된 절을 가질 수 없습니다. 그 후에는 네이밍 된 if를 더 잘 명명되고 구현 된 함수에 넣을 수 있습니다. 따라서 프로그램의 복잡성을 추상화하고 사라진 후에 코드를 읽는 프로그래머에게 그 의미를 유지할 수 있습니다. :)

+0

나는 그 대답을 좋아한다. 내 문제는 중첩 된 if-then 문이 아닙니다. 나는 중첩 된 if를 가지고 있지 않다. 뭔가를하는 트리의 각 리프에 대해 하나의 if (else if) 문을 가지고 있습니다. 따라서 모든 복잡한 작업을 조건부 계산으로 처리했습니다. 제안 된대로 함수를 중첩하고 함수 내에서 중첩을 추상화하는 것이 더 바람직합니까? 감사. – Dale

+1

중첩 또는 긴 if-then 체인이 무엇을하는지 명확하지 않거나 읽을 수 없을 때 추상화하는 것이 가장 바람직합니다. 작은 함수가 긴 if-then chain과 같이 이해하기 어려운 것을 추상화하는 데 사용될 때 이것은 (모든 언어에서) 프로그램에 훨씬 더 많은 가독성을 제공합니다. 엄지 손가락의 규칙으로, 특정 if-then 문이 무엇을하는지 또는 왜 있는지에 대한 설명을 작성해야하는 경우 코멘트가 아닌 잘 알려진 함수에 넣는 것이 좋습니다. 당신의 동료가 당신에게 감사 할 것입니다. – djhaskin987

관련 문제