2016-05-18 4 views
1

私は再帰を練習しています。概念的には、これがどのように機能すべきかを理解していますが(下記参照)、コードは機能しません。Javascript再帰?

私が間違っていることを教えてください。そして、コードの各ステップとその動作を説明してください。明確な説明は、私に働くコードを与えるより10倍優れています。

/* 
    buildList(0, 5) == buildList(0, 5 - 1) // [0] 
    buildList(0, 4) == buildList(0, 4 - 1) // [0,0] 
    buildList(0, 3) == buildList(0, 3 - 1) // [0,0,0] 
    buildList(0, 2) == buildList(0, 2 - 1) // [0,0,0,0] 
    buildList(0, 1) == buildList(0, 1 - 1) // [0,0,0,0,0] 
    */ 

var buildList = function(value, length) { 
    var result = []; 
    if (length === 0) { 
    return result; 
    } 

    result.push(value); 

    return buildList(result.push(value), length - 1); 

}; 


buildList(0, 5); 

概念レベルでの再帰の仕組みを理解しています。

答えて

2

あなたのアプローチが動作しないことができ、それ以外の場合は、再帰の結果を返す:あなたはあなたの関数の外にその変数を宣言すると、コードが動作します。

代わりに、あなたが最初に再帰する必要があり、その後、別の方法として

var buildList = function(value, length) { 
    if (length <= 0) return []; 
    var recur = buildList(value, length-1); 
    recur.push(value); 
    return recur; 
}; 

を押して、基本ケースでは、あなたが間違った二つのことをやっている新しい配列に

var buildList = function(value, length, array=[]) { 
    if (length <= 0) return array; 
    array.push(value); 
    return buildList(value, length-1, array); 
}; 
+0

ありがとうございました! – spaceDog

+1

@spaceDog:代替バージョン内の再帰呼び出しも末尾にあります。つまり、ES2015準拠のエンジンはこの呼び出しを最適化できます(テールコール最適化)。結果として、代替バージョンは命令的ループと同じくらい速くなります。 – rand

+0

@Iven私はパフォーマンスについては考えていませんでした(なぜなら、ループや '[.fill'が良いでしょう)。しかし、良い点です。 [②ality](http://www.2ality.com/2015/06/tail-call-optimization.html)には、テールコールの最適化に関する素晴らしい記事があります。 – Oriol

0

問題は、関数の呼び出しごとに、変数が[]に再初期化されることです。ベースケースは、新しい空の配列を返すので、

var result = []; 
var buildList = function(value, length) { 

    if(length === 0){ 
    return result; 
    } 

    result.push(value); 

    return buildList(result.push(value), length - 1); 

}; 


buildList(0, 5); 
console.log(result); 
+0

ありがとうございます! – spaceDog

+0

非常に良い解決策ではありません。 2つのリストを作成したいとしたら、両方の結果が最初に望む2つのリストを連結してしまうことになります。 – Sylwester

0
/* 
    buildList(0, 5) == buildList(0, 5 - 1) // [0] 
    buildList(0, 4) == buildList(0, 4 - 1) // [0,0] 
    buildList(0, 3) == buildList(0, 3 - 1) // [0,0,0] 
    buildList(0, 2) == buildList(0, 2 - 1) // [0,0,0,0] 
    buildList(0, 1) == buildList(0, 1 - 1) // [0,0,0,0,0] 
    */ 

var result = []; //(1) 

var buildList = function(value, length) { 
    if (length === 0) { 
    return result; 
    } 

    result.push(value); 

    return buildList(value, length - 1); //(2) 

}; 


buildList(0, 5); 

を作成しないようにすることができます:

  1. あなたは初期化しています方法の中でt。これは、再帰的メソッド呼び出しが行われるたびに空の配列に結果をリセットすることを意味します。
  2. 配列をbuildlist()の再帰呼び出しに渡しています。そこに値を渡したいと思っています。
+0

ありがとうございました! – spaceDog

+0

リストを作成して2回目になると、結局は連結で終わるでしょう。あなたが作った最初のリストは同じ配列なので突然変異があっただけでなく... – Sylwester