本エントリは 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 を作成した)
可変リスト使用箇所がなくなり、前より更に良くなった気がする!