現在、瞑想アプリ「Meditation Note」のアップデート作業を行っています。このアプリは私が初めて作成したアプリで、これまでにほとんどダウンロードされていないのですが、思い入れがとても強いアプリです。瞑想関連のアプリはすでにたくさんありますし、現在も新しいタイプのアプリがリリースされ続けているので、PLAYストアで「瞑想」で検索しても表示すらされない状態です。それでも、もともと「自分で使いたい」という想いで作った記念すべき初アプリなので、少しでもいいものにしたいと思いアップデートすることにしました。
まず、今回グラフを追加しようと思い、ソースを調べました。2作目、3作目のアプリでグラフを使ったことがあるので今回は楽かなと思っていたのですが、ソースを見て固まってしまいました。
… グラフに必要なデータである日付と時間が一つの文字列になってる …
// 日本語版 record: { date: "2016/10/31(月) 09:00", ... } // 英語版 record: { date: "Mon. Oct.27, 2016, 09:00 am", ... }
作成当初グラフ化なんて考えてもいなかった(そんな余裕がなかった)からか「日付は表示するだけだから」と文字列にしてしまいました。グラフは、横軸を日付、縦軸を累積時間や回数にしようと思っているので、これを、
record: { date: { y: 2016, m: 9, d: 31, w: 0, s: { h: 9, m: 0 } }, ... }
のような構造にして、同じ月にあたるレコードの時間と個数を集計できる形にしないと。
元の文字列から値を取り出す方法としてまず思いつくのが slice()などを使う方法。文字列の先頭から年にあたる4文字を取り出し、そこから一つ飛ばして、月にあたる2文字を取り出し、さらに、、、って、できないことはないんですけど、なんかイヤな感じが。文字列のインデックスを指定しなくちゃいけないので、ソースコードがごちゃごちゃしちゃうなと。で、悩んだ挙句、正規表現を使うことにしました。前に使ったことはあったのですが、ものの見事にすっかり忘れていて、本読みました。
ソースはこんな感じになりました。
result = date.match(/[^/() :.,]+/g); if (mdt.lang_jp) { // "2016/10/27(木) 9:00" // [0]/[1]/[2]([3]) [4]:[5] record.date.y = Number(result[0]); record.date.m = Number(result[1]); record.date.d = Number(result[2]); record.date.w = Number(WEEK[result[3]]); record.date.s.h = Number(result[4]); record.date.s.m = Number(result[5]); } else { // "Thu. Oct.27, 2016, 9:00 am" // [0]. [1].[2], [3], [4]:[5] [6] record.date.y = Number(result[3]); record.date.m = Number(MONTH[result[1]]); record.date.d = Number(result[2]); record.date.w = Number(WEEK[result[0]]); record.date.s.h = Number(result[4]) + ((result[6] === "pm") ? 12 : 0); record.date.s.m = Number(result[5]); }
正規表現で「/」、「(」、「)」、「 」、「:」、「.」、「,」以外にマッチするパターンを見つけて配列に格納します。この抽出処理がたった一行で済むので、かなり便利です。
正規表現を使うことで複雑な処理を簡潔に記述するということは、些細なことのようでけっこう重要な気がします。なんとか使いこなせるようになりたいです。