[毎日Kotlin] Day18. For loop(ループ処理)

2018.02.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

毎日Kotlinシリーズです。

このシリーズを初めての方はこちらです。「毎日Kotlin」はじめました | Developers.IO

問題

For loop | Try Kotlin

forループで処理できるようにしてみよう。

Kotlin for loop iterates through anything that provides an iterator. Make the class DateRange implement Iterable, so that it could be iterated over. You can use the function MyDate.nextDay() defined in DateUtil.kt

//ここを書き換える
class DateRange(val start: MyDate, val end: MyDate)

fun iterateOverDateRange(firstDate: MyDate, secondDate: MyDate, handler: (MyDate) -> Unit) {
    for (date in firstDate..secondDate) {
        handler(date)
    }
}


data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
    override fun compareTo(other: MyDate) = when {
        year != other.year -> year - other.year
        month != other.month -> month - other.month
        else -> dayOfMonth - other.dayOfMonth
    }
}

operator fun MyDate.rangeTo(other: MyDate) = DateRange(this, other)


fun MyDate.nextDay() = addTimeIntervals(TimeInterval.DAY, 1)

enum class TimeInterval {
    DAY,
    WEEK,
    YEAR
}

fun MyDate.addTimeIntervals(timeInterval: TimeInterval, number: Int): MyDate {
    val c = Calendar.getInstance()
    c.set(year, month, dayOfMonth)
    when (timeInterval) {
        TimeInterval.DAY -> c.add(Calendar.DAY_OF_MONTH, number)
        TimeInterval.WEEK -> c.add(Calendar.WEEK_OF_MONTH, number)
        TimeInterval.YEAR -> c.add(Calendar.YEAR, number)
    }
    return MyDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DATE))
}

狙い

ここで考えて欲しい問題の意図はなんだろうか?

演算子でかっこよく処理する一連の流れをここ数日間実装していますね。どんどんKotlinっぽく記述していけるようにカスタマイズしていこう!

解答例

class DateRange(val start: MyDate, val end: MyDate): Iterable<MyDate>{
    override fun iterator(): Iterator<MyDate> = DateIterator(this)
}

class DateIterator(val dateRange:DateRange) : Iterator<MyDate> {
    var current: MyDate = dateRange.start
    override fun next(): MyDate {
        val result = current
        current = current.nextDay()
        return result
    }
    override fun hasNext(): Boolean = current <= dateRange.end
}

[毎日Kotlin] Day15. Comparison(演算子), [毎日Kotlin] Day16. In range,[毎日Kotlin] Day17. Range toの続きだったのですが、わかりやすくそれぞれの演算子に対応するクラスをつくって、それに変換するコードにしているようです。

たしかにわかりやすい。真似ていこう。

hasNextは次の要素とendを比較してつくっていますね。Iteratorが意外と簡単に作れてしまう。これを使って何か作ってみたくなってきました。

あとがき

Day19.でまたお会いしましょう。