318

a.xの各要素を合計したいとしarrます。

arr = [ { x: 1 }, { x: 2 }, { x: 4 } ];
arr.reduce(function(a, b){ return a.x + b.x; }); // => NaN

a.x私はそれがundefinedある時点であると信じる理由があります。

以下は正常に動作します

arr = [ 1, 2, 4 ];
arr.reduce(function(a, b){ return a + b; }); // => 7

最初の例で何が間違っていますか?

4

19 に答える 19

394

最初の反復の後、数値を返し、そのプロパティを取得xして次のオブジェクトに追加undefinedしようとしていundefinedますNaN

xパラメータの x プロパティの合計を持つプロパティを含むオブジェクトを返してみてください:

var arr = [{x:1},{x:2},{x:4}];

arr.reduce(function (a, b) {
  return {x: a.x + b.x}; // returns object with property x
})

// ES6
arr.reduce((a, b) => ({x: a.x + b.x}));

// -> {x: 7}

コメントから追加された説明:

次の反復で変数[].reduceとして使用される各反復の戻り値。a

反復 1: a = {x:1}b = {x:2}、反復 2で{x: 3}割り当てられたa

繰り返し 2: a = {x:3}, b = {x:4}.

あなたの例の問題は、数値リテラルを返していることです。

function (a, b) {
  return a.x + b.x; // returns number literal
}

反復 1: a = {x:1}b = {x:2}、次の反復の// returns 3ようにa

反復 2: a = 3b = {x:2}戻り値NaN

数値リテラル3には (通常) と呼ばれるプロパティがないxため、undefined常に undefined + b.x返さNaNれ、NaN + <anything>常に返されます。NaN

明確化: オプションのパラメーターを渡して魔法の数を減らして数値プリミティブを取得する方がクリーンであるという考えに同意しないため、このスレッドの他の上位の回答よりも私の方法を好みます。書き込まれる行が少なくなる可能性がありますが、読みにくくなります。

于 2011-04-20T14:34:53.853 に答える
389

これを実現するよりクリーンな方法は、 の 2 番目の引数として初期値を指定することreduceです。

var arr = [{x:1}, {x:2}, {x:4}];
var result = arr.reduce(function (acc, obj) { return acc + obj.x; }, 0);
console.log(result);  // 7

無名関数が初めて呼び出されると、 で呼び出され(0, {x: 1})、 が返されます0 + 1 = 1。次回は で呼び出されて(1, {x: 2})を返します1 + 2 = 3。次に で呼び出され(3, {x: 4})、最終的に が返され7ます。

これは、配列が空の場合も処理し、 を返し0ます。

于 2011-06-09T23:57:18.597 に答える
37

他の人がこの質問に答えていますが、私は別のアプローチで投げたいと思いました. 合計 ax に直接移動するのではなく、マップ (ax から x へ) を結合し、reduce (x を追加する) ことができます。

arr = [{x:1},{x:2},{x:4}]
arr.map(function(a) {return a.x;})
   .reduce(function(a,b) {return a + b;});

確かに、おそらく少し遅くなるでしょうが、オプションとして言及する価値があると思いました.

于 2011-04-21T15:21:09.913 に答える
9

指摘されたことを形式化するために、リデューサーは、偶然に同じ型である可能性のある2つの引数を取り、最初の引数に一致する型を返すカタモルフィズムです。

function reducer (accumulator: X, currentValue: Y): X { }

つまり、レデューサーの本体は、currentValueの現在の値をaccumulator新しい の値に変換する必要がありますaccumulator

アキュムレータと要素の値は両方ともたまたま同じ型である (ただし目的は異なる) ため、これは加算時に簡単に機能します。

[1, 2, 3].reduce((x, y) => x + y);

これらはすべて数値であるため、これは機能します。

[{ age: 5 }, { age: 2 }, { age: 8 }]
  .reduce((total, thing) => total + thing.age, 0);

ここで、アグリゲーターに開始値を与えています。ほとんどの場合、開始値は、アグリゲーターが期待するタイプ (最終値として出力されると予想されるタイプ) である必要があります。これを強制されているわけではありません (強制されるべきではありません) が、心に留めておくことが重要です。

それがわかれば、他の n:1 関係の問題に対して意味のある還元を書くことができます。

繰り返される単語の削除:

const skipIfAlreadyFound = (words, word) => words.includes(word)
    ? words
    : words.concat(word);

const deduplicatedWords = aBunchOfWords.reduce(skipIfAlreadyFound, []);

見つかったすべての単語の数を提供する:

const incrementWordCount = (counts, word) => {
  counts[word] = (counts[word] || 0) + 1;
  return counts;
};
const wordCounts = words.reduce(incrementWordCount, { });

配列の配列を単一のフラットな配列に減らす:

const concat = (a, b) => a.concat(b);

const numbers = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
].reduce(concat, []);

ものの配列から 1:1 に一致しない単一の値に移行しようとするときはいつでも、reduce を検討することができます。

実際、 map と filter は両方ともリダクションとして実装できます。

const map = (transform, array) =>
  array.reduce((list, el) => list.concat(transform(el)), []);

const filter = (predicate, array) => array.reduce(
  (list, el) => predicate(el) ? list.concat(el) : list,
  []
);

これにより、 の使用方法に関するさらなるコンテキストが提供されることを願っていますreduce

これに加えて、まだ詳しく説明していませんが、配列要素が関数であるため、入力と出力の型が動的であることを明確に意図していることが予想される場合です。

const compose = (...fns) => x =>
  fns.reduceRight((x, f) => f(x), x);

const hgfx = h(g(f(x)));
const hgf = compose(h, g, f);
const hgfy = hgf(y);
const hgfz = hgf(z);
于 2016-11-12T19:58:57.960 に答える
5

{x:???}削減の各ステップで、新しいオブジェクトを返すことはありません。したがって、次のいずれかを行う必要があります。

arr = [{x:1},{x:2},{x:4}]
arr.reduce(function(a,b){return a + b.x})

またはあなたがする必要があります

arr = [{x:1},{x:2},{x:4}]
arr.reduce(function(a,b){return {x: a.x + b.x}; }) 
于 2011-04-20T14:35:42.600 に答える
0

次のようにreduceメソッドを使用できます。0(ゼロ)を1などに変更すると合計数に加算されます。たとえば、この例では合計数が 31 になりますが、0 を 1 に変更すると、合計数は 32 になります。

const batteryBatches = [4, 5, 3, 4, 4, 6, 5];

let totalBatteries= batteryBatches.reduce((acc,val) => acc + val ,0)
于 2020-10-26T21:51:38.550 に答える