本エントリは Scala で ATND API を叩く、Scala で partition 関数を使用してリストの要素を振り分けるの続きです。
さて、ここまでくるともうひとつの ListBuffer 使用箇所も不変リストにしたい。したほうがいいはずだ、多分。
残った ListBuffer 使用箇所は、「"keyword=aaa,bbb", "ym=201207", "ymd=20120723"」といった要素を持つリストを用意して
mkString("&") で「"keyword=aaa,bbb&ym=201207&ymd=20120723"」といった文字列を作っている。
(話はそれるけど、要素の区切り文字や接頭辞・接尾辞をつけた文字列を作れる mkString って便利)
さて、ここまでくるともうひとつの ListBuffer 使用箇所も不変リストにしたい。したほうがいいはずだ、多分。
残った ListBuffer 使用箇所は、「"keyword=aaa,bbb", "ym=201207", "ymd=20120723"」といった要素を持つリストを用意して
mkString("&") で「"keyword=aaa,bbb&ym=201207&ymd=20120723"」といった文字列を作っている。
(話はそれるけど、要素の区切り文字や接頭辞・接尾辞をつけた文字列を作れる mkString って便利)
「::」で要素を連結したリストを作れば上手くいくのでは、と思い付き、以下のようにやってみた。
空であれば空文字を返すようにした。
一見うまくいったっぽいけど、空文字はリストの要素なので、例えば何も引数を渡さないと getParams が「&&」という文字列を返してしまう。
(空文字3つのリストなので、空文字・&・空文字・&・空文字が返る)
期待する動作は「&&」ではなくて空文字を作ってほしいので、別の方法を考える。
「:::」で連結してみよう。
createSearchQuery で元の要素が何もなければ空リストを返すようにした。
これで何も引数を渡さないと getParams が空文字を返してくれるようになった。
(本題と関係ないけど、日付かどうかの判定を正規表現から
SimpleDateFormat で厳密にパースできるかどうかで判定する validDateFormat を作成した)
可変リスト使用箇所がなくなり、前より更に良くなった気がする!
import scala.io.Source
import scala.xml.XML
import java.text.SimpleDateFormat
val source = Source.fromURL("http://api.atnd.org/events/?" + getParams(args))
val response = XML.loadString(source.mkString)
val orgFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
val showFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm")
response \\ "event" foreach { e =>
println("『%s』\n %s\n %s\n" format(
e \\ "title" text,
showFormat.format(orgFormat.parse(e \\ "started_at" text)),
e \\ "place" text))
}
def getParams(args:Array[String]):String = {
val ymPattern = """^\d{6}$""".r
val ymdPattern = """^\d{8}$""".r
val (ymList, otherList) = args partition (ymPattern.findFirstIn(_) != None)
val (ymdList, keywordList) = otherList partition (ymdPattern.findFirstIn(_) != None)
val paramsList =
createSearchQuery("keyword", keywordList) ::
createSearchQuery("ym", ymList) ::
createSearchQuery("ymd", ymdList) ::
List()
paramsList.mkString("&")
}
def createSearchQuery(key:String, params:Array[String]):String = {
if (!params.isEmpty) {
key + "=" + params.mkString(",")
} else {
""
}
}
「::」は要素となる型を先頭に追加したリストを作るので、createSearchQuery で要素が空でなければキーと値を文字列にして、空であれば空文字を返すようにした。
一見うまくいったっぽいけど、空文字はリストの要素なので、例えば何も引数を渡さないと getParams が「&&」という文字列を返してしまう。
(空文字3つのリストなので、空文字・&・空文字・&・空文字が返る)
期待する動作は「&&」ではなくて空文字を作ってほしいので、別の方法を考える。
「:::」で連結してみよう。
import scala.io.Source
import scala.xml.XML
import java.text.ParseException;
import java.text.SimpleDateFormat
val source = Source.fromURL("http://api.atnd.org/events/?" + getParams(args))
val response = XML.loadString(source.mkString)
val orgFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
val showFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm")
response \\ "event" foreach { e =>
println("『%s』\n %s\n %s\n" format(
e \\ "title" text,
showFormat.format(orgFormat.parse(e \\ "started_at" text)),
e \\ "place" text))
}
def getParams(args:Array[String]):String = {
val ymFormat = new SimpleDateFormat("yyyyMM")
ymFormat.setLenient(false)
val ymdFormat = new SimpleDateFormat("yyyyMMdd")
ymdFormat.setLenient(false)
val (ymList, otherList) = args partition (validDateFormat(_, ymFormat))
val (ymdList, keywordList) = otherList partition (validDateFormat(_, ymdFormat))
val paramsList =
createSearchQuery("keyword", keywordList) :::
createSearchQuery("ym", ymList) :::
createSearchQuery("ymd", ymdList)
paramsList.mkString("&")
}
def validDateFormat(arg:String, fmt:SimpleDateFormat):Boolean = {
try {
fmt.parse(arg)
true
} catch {
case _:ParseException => false
}
}
def createSearchQuery(key:String, params:Array[String]):List[String] = {
if (!params.isEmpty) {
List(key + "=" + params.mkString(","))
} else {
List()
}
}
「:::」はリスト同士を連結して新しいリストを作る。createSearchQuery で元の要素が何もなければ空リストを返すようにした。
これで何も引数を渡さないと getParams が空文字を返してくれるようになった。
(本題と関係ないけど、日付かどうかの判定を正規表現から
SimpleDateFormat で厳密にパースできるかどうかで判定する validDateFormat を作成した)
可変リスト使用箇所がなくなり、前より更に良くなった気がする!