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

JavascriptでWeb storageでデータを保存しています。データを読みだして配列に入れる際、必要なデータのみを抽出したいと考えています。アドバイス頂きようやく形はできたのですがいくつか疑問点があります。
タブからユーザー名を選択して保存ボタンを押すと、現在時刻をファイル名にしてデータが保存されます。
ユーザー名を変えて保存し何度か繰り返します。保存されたデータを読みだす際に例えば”青木”というユーザー名だけ抽出してリスト表示させたいのですがなぜかリストの中に空データが入ってしまいます。青木のみを抽出したのですが、この空データは他のユーザー名のものなのかよく理解できませんでした。空のデータを除外することはできるのでしょうか?また、青木のデータの中の配列で得点のところ(100点)だけ抽出して表示させるやり方がよくわかりません。(青木のデータのみを保存順番に、上から表示させたい(空データを除く))もしかして、<DIV>の表示枠のほうで配列の形式などで、必要な部分だけを出力するのかとも考えたのですが、うまくできませんでした。是非ともアドバイス頂ければ幸いです。宜しくお願いします。

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

▽最新の回答へ

質問者から

https://jsfiddle.net/kajironpu/wvh46tmf/1/

こちらにJS fiddleにサンプルのコードを入力しました。


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

ざっくり言うと、ストレージのデータを抜き出しているループの中で、青木のデータを抜き出して出力、としているのが期待通りにならない原因です。
ストレージのデータを全て抜き出してから、青木のデータだけにして出力、です。

読み込みボタンを押したときの処理を書き直しました。
元のソースを極力残してます。

//読込ボタンをクリックした時の処理
document.getElementById("load").addEventListener("click",function(){
// localStorage.key(i)でi番目のデータのkeyが取れる。

 // ストレージのデータをすべて抜き出す
 var dataArray=[];
 for (var i=0; i<localStorage.length; i++){
 var k = localStorage.key(i);
 dataArray[i] =JSON.parse(localStorage.getItem(k));

 }

 // x に「青木」のデータだけを抽出する
 var x = dataArray.filter(function(e){return e[1]=="青木"});

 // 青木のデータを全て出力する
 x.forEach(function(data) {
 document.getElementById("list").innerHTML += '<font size="5" color="#0000ff"><TABLE border=1 cellpadding=0 cellspacing=5><tr><TD bgcolor="#FFCCCC">'+data+'<font></td></tr></table>';
 });

},false);

欲しいのが「青木」のデータだけであれば、ストレージから抜き出すときにはねちゃう方が素直だと思います。

//読込ボタンをクリックした時の処理
document.getElementById("load").addEventListener("click",function(){
// localStorage.key(i)でi番目のデータのkeyが取れる。

 // ストレージのデータから「青木」のデータだけを取り出す
 var dataArray=[];
 for (var i=0; i<localStorage.length; i++){
 var k = localStorage.key(i);
 var v = JSON.parse(localStorage.getItem(k));
 if (v[1] == "青木") {
 dataArray.push(v);
 }

 }

 // 青木のデータを全て出力する
 dataArray.forEach(function(data) {
 document.getElementById("list").innerHTML += '<font size="5" color="#0000ff"><TABLE border=1 cellpadding=0 cellspacing=5><tr><TD bgcolor="#FFCCCC">'+data+'<font></td></tr></table>';
 });

},false);


あ、Storage#key() が保存した順番の逆順で取り出しちゃうみたいです。
並べ替えの処理も入れると、こうなります。

//読込ボタンをクリックした時の処理
document.getElementById("load").addEventListener("click",function(){
// localStorage.key(i)でi番目のデータのkeyが取れる。

 // ストレージのデータをすべて抜き出す
 var dataArray=[];
 for (var i=0; i<localStorage.length; i++){
 var k = localStorage.key(i);
 var v = JSON.parse(localStorage.getItem(k));
 if (v[1] == "青木") {
 dataArray.push(v);
 }

 }

 // データを日時で並べ替える
 dataArray = dataArray.sort(function(a, b) {
 if (a[0] > b[0]) {
 return 1;
 } else if (a[0] < b[0]) {
 return -1;
 }
 return 0;
 });

 // 青木のデータを全て出力する
 dataArray.forEach(function(data) {
 document.getElementById("list").innerHTML += '<font size="5" color="#0000ff"><TABLE border=1 cellpadding=0 cellspacing=5><tr><TD bgcolor="#FFCCCC">'+data+'<font></td></tr></table>';
 });

},false);

Array#sort メソッドが配列を返すので、sort メソッドの戻り値に forEach メソッドを呼び出して、という書き方もできます。

 // 青木のデータを日時で並べ替えて、全て出力する
 dataArray.sort(function(a, b) {
 if (a[0] > b[0]) {
 return 1;
 } else if (a[0] < b[0]) {
 return -1;
 }
 return 0;
 }).forEach(function(data) {
 document.getElementById("list").innerHTML += '<font size="5" color="#0000ff"><TABLE border=1 cellpadding=0 cellspacing=5><tr><TD bgcolor="#FFCCCC">'+data+'<font></td></tr></table>';
 });

こっちの書き方は慣れないと分かりにくいかもしれませんが、jQuery を使う場合にはこっちの書き方が主流です。


kajironpuさんのコメント
ありがとうございます! とてもよく理解できました。 結果を表示する順番も、時間順に並んでなかったので、原因がわからず、いろいろ調べていた所でした。 dataArray.push(v); これは、ユーザごとに、必要なデータだけを、配列に入れているのですね。 なかなかこのアイデアが思いつかず、なるほど?と思ったところです。 1つ、1つクリアになっていき、すごく楽しいです。 いろいろありがとうございました。

kajironpuさんのコメント
またまた1つわからないことがあります。 ユーザーに関係なく、全員のデータの中から得点の高い順に並び替えを行いたいのですが、 ユーザー全員のデータを新しい配列に入れてみました。(dataArray2) そして、dataArray2の中の4番目の配列(得点データ)ごとに並べ替えたところ(↓のコードです) 点数順に並んだのですが、全データの中には、同じユーザーが繰り返し問題を解いた結果が 複数入っています。 例)1位 青木 100点 2位 青木 49点 3位 太田 56点 この配列の中から同じユーザーのものから、ダブりを消したいのですが、 (例えば、青木は点数の高い100点のほうだけを残す) そのやり方を教えて下さい。ユーザー名を比較して同じだったら、さらに配列の4つめの点数を見て大きい方を別の配列にpushするというやり方になりますか? あるいは、もっと簡単にする方法はあるのでしょうか? >|| // 配列を入れ替えて、得点を一番先に持ってくる dataArray2 = dataArray2.sort(function(a, b) { if (a[4] > b[4]) { return -1; } else if (a[4] < b[4]) { return 1; } return 0; }); ||<

a-kuma3さんのコメント
考え方は合ってると思います。 別の配列に push で追加していくのとあまり変わりませんが、Array#filter メソッドが使えます。 こんな感じ。 >|javascript| // 点数は、文字列じゃなくて、数値としておきます var dataArray = [ ["yyyy/mm/dd", "青木", "title", 100], ["yyyy/mm/dd", "青木", "title", 49], ["yyyy/mm/dd", "太田", "title", 50], ["yyyy/mm/dd", "鈴木", "title", 0], ["yyyy/mm/dd", "太田", "title", 77], ["yyyy/mm/dd", "鈴木", "title", 22], ]; // 点数の高い順に並び替え var sorted = dataArray.sort(function(a, b) { if (a[3] > b[3]) { // 点数は 4番目なので [3] return -1; // 大きい順 } else if (a[3] < b[3]) { return 1; } return 0; }); // 重複を取り除く var userMap = {}; // 一度出てきた名前を持っておく変数 var ranking = sorted.filter(function(data) { if (! userMap[data[1]]) { // userMap に名前 (2番目) があるか? userMap[data[1]] = data[1]; // 名前を登録 return true; // このデータを採用 } return false; // userMap に名前が登録されていたら、採用しない }); // ランキング ranking.forEach(function(a) { console.log(a); }); ||<

kajironpuさんのコメント
ありがとうございます。さっそく試してみましたがうまくいきました。 重複を取り除くところのやり方がなかなか難しいですね いろいろ自分で考えてアイデアが思い浮かんで、それを実際の形にするところがまだまだです。 ↑のやり方をしっかり勉強したいと思います。 どうもありがとうございました!

kajironpuさんのコメント
追加、追加の質問で恐縮です。 http://log.noiretaya.com/239 chart.js というものをつかって、棒グラフに挑戦しています。 横軸が、先ほどの↑のスクリプトの日付、つまりdata[0] 縦軸をスコアdata[3]にしたいのですが http://log.noiretaya.com/239 ↑こちらのサイトのchart.jsの中の data : [1, 59, 90, 81, 56, 55, 40, 30, 10, 40, 48, 58] この部分の配列にそっくり差し替えたいのですが そのやり方がよくわかりませんでした。 data: data[3]のようにしてみたのですが、動作しません。 data : [1, 59, 90, 81, 56, 55, 40, 30, 10, 40, 48, 58] この部分を、スコアの配列のデータに置き換えることはできるのでしょうか?

a-kuma3さんのコメント
例えば、青木さんのデータがこれまでのやり取りのような dataArray に入ってるとします。 dataArray[0] は、一回目のデータ。 dataArray[0][3] は、一回目の得点です。 dataArray[1] は、二回目のデータ。 dataArray[1][3] は、二回目の得点です。 # 日時で並べ替えされてるとして。 chart.js に渡す data には、以下のように設定することになります。 >|| data : [ dataArray[0][3], dataArray[1][3], dataArray[2][3], ... ] ||< 回答履歴の個数が分からないので、このように、ひとつひとつ書くわけにはいかないので、Array#push の出番です。 得点だけを詰めた配列を Chart に渡す引数に設定します。 >|javascript| // 得点だけを詰めた配列を作る var pointArray = []; dataArray.forEach(function(data) { pointArray.push(data[3]); }); ... var barChartData = { labels : ... datasets : [ [ ... data : pointArray // 特典の配列を data に設定する ] ... ] }; ||< 試してないけど、こんな感じです。

kajironpuさんのコメント
ありがとうございました。おかげさまで無事表示することができました。 配列のデータを抜き出すやり方が理解できず困っていたのですが ようやく理解できました。 pointArray.push(data[3]); でスコアデータを配列にどんどん追加していくのですね。 dataArray自体は、2次配列みたいになっていますがそこから 点数の部分だけを集めるには、 dataArray.forEach(function(data) { pointArray.push(data[3]); このようなやり方を使うのですね。なかなか難しいですが、うまく使いこなせるように練習したいと思います。 ありがとうございました。
関連質問

●質問をもっと探す●



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