人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

javascriptで平均値を求めたいのですが
Aさん、Bさん、Cさんのスコアデータが配列に順番に入っています。

Aさん、10点
Bさん、50点
Cさん、100点
Aさん、22点
Bさん、44点
Bさん、40点
Cさん、100点

それぞれ日付ごとにスコアデータを記録したものを順番に配列に入れています。

data =[A,10月2日,10,B,10月3日,50,C,11月1日,100,A,12月1日,22,B,12月1日,44,B,11月3日,40,C,10月10日,100]のように
ユーザ名、日付、点数という履歴のデータを配列に順番にいれているのですが
ここからそれぞれのユーザーごとに平均値を求めたいと思っています。


例)
Aさんの平均値 *点
Bさんの平均値 *点
Cさんの平均値 *点

この場合、同じユーザ名のところを集めて点数を足していってそれぞれ数で割って平均値を出すやり方がいまいちわかりません。ユーザ名ごとに点数を足すやり方は連想配列を使ってやるのでしょうか?(ユーザ名をキーにする?)

アドバイス頂ければ幸いです。

●質問者: javelover
●カテゴリ:ウェブ制作
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● a-kuma3
ベストアンサー

ユーザ名をキーにした連想配列にデータを貯めこんでいく、という方針で良いと思います。
例えば、こんな感じ。

// 集計するデータ
var data =[
 "A", "10月2日", 10,
 "B", "10月3日", 50,
 "C", "11月1日", 100,
 "A", "12月1日", 22,
 "B", "12月1日", 44,
 "B", "11月3日", 40,
 "C", "10月10日", 100
];

// 合計点数と回答数を入れておく連想配列
var info = {};

// 合計点数と回答数をユーザ毎に集計する
for (var i = 0 ; i < data.length ; i += 3) { // みっつ毎
 var name = data[i]; // 一番目が名前
 var point = data[i+2]; // 三番目が点数

 var e = info[name]; // 合計点数と回答数を取り出す
 if (! e) { // 初めてのカウントだったら
 e = {}; // 合計点数=0、回答数=0 のデータを用意
 e.sum = 0;
 e.n = 0;
 }
 e.sum += point; // 合計点数をカウント
 e.n += 1; // 回答数をカウント
 info[name] = e; // カウントしたデータを入れ直す
}

// 集計したデータから平均値を算出する
for (var name in info) { // 連想配列のデータを順番に取り出す
 var e = info[name]; // キーが名前
 var ave = e.sum / e.n; // 平均値

 // 計算した平均値などをコンソールに出力
 console.log(name, e.sum, e.n, ave);
}




追記です。

キーではなくaverageを点数が高い順に並べ替えするのはどうしたらいいのでしょうか?

先の回答を、ちょっと書き換えてみました。

// 集計するデータ
var data =[
 "A", "10月2日", "10",
 "B", "10月3日", "50",
 "C", "11月1日", "100",
 "A", "12月1日", "22",
 "B", "12月1日", "44",
 "B", "11月3日", "40",
 "C", "10月10日", "100"
];

// 合計点数と回答数を入れておく連想配列
var info = {};

// 合計点数と回答数をユーザ毎に集計する
for (var i = 0 ; i < data.length ; i += 3) { // みっつ毎
 var name = data[i]; // 一番目が名前
 var point = parseInt(data[i+2]); // 三番目が点数

 var e = info[name]; // 合計点数と回答数を取り出す
 if (! e) { // 初めてのカウントだったら
 e = {}; // 合計点数=0、回答数=0 のデータを用意
 e.sum = 0;
 e.n = 0;
 }
 e.sum += point; // 合計点数をカウント
 e.n += 1; // 回答数をカウント
 info[name] = e; // カウントしたデータを入れ直す
}

// 平均得点と名前を入れる配列
var ave_list = [];

// 集計したデータから平均値を算出する
for (var name in info) { // 連想配列のデータを順番に取り出す
 var e = info[name]; // キーが名前
 var ave = e.sum / e.n; // 平均値

 // 計算した平均値と名前を配列に入れる
 ave_list.push([ave, name]);
}

// 平均得点の大きい順に並べ替える
ave_list = ave_list.sort(function(a, b) { return b[0] - a[0]; });

// 名前と平均得点をコンソールに出力する
for (var i = 0 ; i < ave_list.length ; ++i) {
 console.log(ave_list[i][1], ave_list[i][0]);
}

求めた平均値と名前を持った配列を別に作り、それを平均得点順に並べ替えてます。


javeloverさんのコメント
a-kumaさん、ありがとうございます。お返事遅れてすみませんでした。 今、いろいろ理解しながら試していました。 どうも平均値の計算結果がおかしく 1つずつ結果を出力しながら確認したところ、 例えばAさんは10点+22点=16点(平均値)のはずが、1022点÷2=511点となっていました。これは、raw dataの数字が文字認識しているのですね? これを数値変換すればいいのでしょうか。 ちょっと試してみます。

a-kuma3さんのコメント
>> 例えばAさんは10点+22点=16点(平均値)のはずが、1022点÷2=511点となっていました。これは、raw dataの数字が文字認識しているのですね? これを数値変換すればいいのでしょうか。 << 数値変換には parseInt 関数を使ってください。 念のため、第2引数に 10 を指定しておきましょう。 >|javascript| str = "22"; num = parseInt(str, 10); // 十進数として数値化する ||<

javeloverさんのコメント
うまくいきました。ありがとうございます! あとユーザーごとではなく、averageごとに連想配列のデータソートしたいと考えております。連想配列の中のキーでソートする方法はわかったのですが、キーではなくaverageを点数が高い順に並べ替えするのはどうしたらいいのでしょうか?

a-kuma3さんのコメント
>> キーではなくaverageを点数が高い順に並べ替えするのはどうしたらいいのでしょうか? << 回答に追記しました。

javeloverさんのコメント
ありがとうございます。 無事成功しました。averageの結果をもう一度、連想配列に戻すことばかり考えていたのですが、平均値を計算した結果とユーザ名を別の配列に入れてそれをソートするアイデアが思い浮かびませんでした。 いろいろと勉強になりました。ありがとうございます。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ