Javascriptのreduceとfindを組み合わせた際の処理について
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 115
前提・実現したいこと
Javascriptを使ってデータ集計を行っており、reduceやfindを組み合わせた効率的な処理の理解をしたいです。
他サイトを参考にコードをくみ上げたのですが、良く処理を理解できず。
reduceはreturnしたものをどんどん積算していく処理の認識です。
しかし下記コードを動かしたところ、elはreturnしていないのですが、bushoの中にelで計算した結果が入っております。
これはどういう動きをしているのでしょうか。
※以下のサイトを参考にしました。
[https://qiita.com/zaburo/items/fc8f74d144d73b7d70b6]
・応用-GroupBy的な
を参照
該当のソースコード
window.getData = function(data,year){
var busho = data.reduce(function (result, current) {
if(current.nendo == year){
var el = result.find(function (p) {
return p.futanbusho === current.futanbusho
});
if (el) {
el.goukei += Number(current.goukei);
} else {
result.push({
nendo:current.nendo,
futanbusho:current.futanbusho,
goukei:current.goukei
});
}
}
return result;
}, []);
return busho;
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
[]
がinitialValueとして渡されていて、それがresultに入っているものにpush
をしているので値が入ります。
【Array.prototype.reduce() - JavaScript | MDN】
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
initialValue Optional
callback の最初の呼び出しの最初の引数として使用する値。initialValue が与えられなかった場合、配列の最初の要素がアキュムレーターの初期値として使用され、currentValue としてスキップされます。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2021/01/13 20:46 編集
pushでresultに入れていることは理解しました。
私のコードですと、pushでcurrentを入れている認識です。
if(el)の中の処理で、elはreturnもpushもしていないのですが、この計算結果が最終的にresultにも反映されています。それがどうしても理解できないのですが、わかりますでしょうか?
2021/01/13 21:51
elは有る場合オブジェクトなので、書き換えることが可能です。
var o1 = [{a:0},{a:1}];
var o2 = o1.find(function (p){return p.a === 0;});
o2 .a = 2;
console.log(o1 );
2021/01/13 23:00
el は result から find したオブジェクトですよね。で (el を含む) result の全体を return しているのですから、accumulator が更新され続けることに違和感ないと思いませんか?
2021/01/14 09:21
ご回答ありがとうございます。
お二人から頂いた内容を見て、理解できたような気がします。
私は result.find で条件に合致した内容が el に渡される際の挙動が、
値のコピーだと思っていたのですが、そうではなく条件に合致した部分の参照が入っているということですよね?(言葉が不正確かもしれませんが。。。)
(kei344さんに記載いただいたコードで言うと、var o1 = [{a:0},{a:1}]; の {a:0}への参照が find により o2 に格納される)
そのため、その後 o2 の値を弄ると、元であるo1の値も修正される。
上記の理解で合っていますでしょうか?
2021/01/14 09:33 編集
> https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/find
> find() メソッドは、提供されたテスト関数を満たす配列内の 最初の要素 の 値 を返します。
find したものが object であるとき "値" が何を指しているのか、という問題かと。
--
const array1 = [5, 12, 8, 130, 44];
const array2 = [{a:1},{a:2}];
let found1 = array1.find(element => element > 100);
found1++;
console.log(array1);
let found2 = array2.find(element => element.a > 1);
found2.a++;
console.log(array2);
--
は
--
> Array [5, 12, 8, 130, 44]
> Array [Object { a: 1 }, Object { a: 3 }]
--
このような出力になります。
2021/01/14 21:12
回答ありがとうございます。
自分で頂いたコードを動かしてみて納得できました。
頂いたリンク先の説明の「要素の値を返す」という言葉をうまく飲み込めなかったのですが、
頂いたコードの2パターンの違いから理解できたと思います。
found1では説明通り最初尾要素の値を返している(=コピーしている)。そのため更新してもarray1には影響なし。
found2ではオブジェクト内の一致した要素のアドレス的なものを返している(=同じところを見ている)。そのため、found2を更新すると結果としてarray2も更新したことになる)
改めてお二方とも、お忙しいところご丁寧にご回答いただき、本当にありがとうございました。
また機会ございましたら、その際はよろしくお願いいたします。