2017-04-02 18 views
0

私は入力として配列をとる関数を記述しようとしています。正の整数の場合は、それを数えます。整数が負の場合は、それを合計します。reduce()の最初の引数がundefinedを返すのはなぜですか?

私は、jsのreduce()ヘルパーがこれを実行する最良の方法だと考えましたが、実行時に最初の引数のために未定義に戻し続けます。ここで

は私のコードです:

function countPositivesSumNegatives(input) { 
    let countPositive = 0; 
    let sumNegative = 0 

    if (input === null || input === []){ 
     return []; 
    } else { 
     return input.reduce(function(prev,num){ 
     if (num > 0) { 
     countPositive++; 
     }else{ 
     sumNegative = prev + num}; 
     }, 0); 
    } 
    return [countPositive, sumNegative]; 
} 

それは私に言うTypeError例外スロー:

TypeError例外を:プロパティを読み取ることができません '0' 未定義

の私は、コンソールに '前へ' にログインすると、 reduce関数の中で、最初のものを除くすべての入力に対してundefinedを記録します。最初のものは期待どおり0です。しかし、それ以降の各入力については未定義で記録されます。なぜこうなった?

ありがとうございます。

答えて

4

あなたは.reduce()に渡すコールバックは、あなたが何を返却されていないので、あなたは、ループの次の反復のためundefinedを得る。ループの次の繰り返しにprevとして渡される値(累積値を返す必要があります。

これは、ループ内の2つの値を追跡するために行っている作業が複雑になるため、prevを使用しないようにする必要があります。そうしないと、データ構造には両方の値が含まれています。使用方法は.reduce()の教科書の例ではありません。コードは.forEach()またはfor/ofを使用する反復で簡単でしょう。

function countPositivesSumNegatives(input) { 
    let countPositive = 0; 
    let sumNegative = 0 

    if (!input || input.length === 0){ 
     return []; 
    } else { 
     input.forEach(function(num){ 
     if (num > 0) { 
      ++countPositive; 
     } else { 
      sumNegative += num; 
     }); 
    } 
    return [countPositive, sumNegative]; 
} 
+0

ああ、それは理にかなっています。私はreduce()について教えている人がいつもコールバックの一部であることを強調しています。 – newman

+0

また、空の配列の条件付きテストは無効です – charlietfl

+0

@newman - '.forEach()'を使って実装を追加しました。これは '.reduce()'をここに合わせようとするより簡単です。 – jfriend00

0

残念ですが、この機能はうまく実装されていません。しかし、私たちはあなたの機能を次のように修正することができます。

function countPositivesSumNegatives(input) { 
 
    let countPositive = 0; 
 
    let sumNegative = 0; 
 

 
    if (input === null || input === []){ 
 
     return []; 
 
    } else { 
 
     sumNegative = input.reduce(function(prev,num){ 
 
            if (num > 0) { 
 
             countPositive++; 
 
            } else { 
 
             prev += num; 
 
             } 
 
            return prev; // <---- THE MISSING PART 
 
            }, 0); 
 
     } 
 
    return [countPositive, sumNegative]; 
 
} 
 
var data = [1,2,3,4,5,-4,7,-3]; 
 
console.log(countPositivesSumNegatives(data));

しかしコードが、それはまだ多くの問題を伴うだけで正常に動作している間。 .reduce()のようなファンクタに入るときは、自分自身の中に永遠に存在するものを保つことができ、外側のスコープの変数を参照すべきではありません。したがって、このコードを次のように簡単に言い換えることができます。

var data = [1,2,3,4,5,-4,7,-3], 
 
    cpsn = a => a.reduce((p,c) => c > 0 ? (p[0]++,p) : (p[1]+=c,p) ,[0,0]); 
 
console.log(cpsn(data))

関連する問題