2 回答

TA貢獻1786條經驗 獲得超11個贊
package days
import java.lang.IllegalArgumentException
class DaysFactory {
fun dayFromInt(index: Int): Day {
return when (index) {
0 -> Day.Sunday
1 -> Day.Monday
2 -> Day.Tuesday
3 -> Day.Wednesday
4 -> Day.Thursday
5 -> Day.Friday
6 -> Day.Saturday
else -> throw IllegalArgumentException("illigal index :$index")
}
}
enum class Day(val index: Int) {
Sunday(0), Monday(1), Tuesday(2), Wednesday(3), Thursday(4), Friday(5), Saturday(6)
}
}
class DaysRange(val seed: String) {
var stringFormat = ""
private fun getTomorrow(dayIndex: Int): Int {
if (dayIndex != 6) return dayIndex + 1
return 0
}
override fun toString(): String =stringFormat
init {
if (isValidInput(seed)) {
val dayFactory = DaysFactory()
val indexes = seed.split(",").map { it.toInt() }
val days = indexes.map { dayFactory.dayFromInt(it) }
val ranges = splitIndexesToRanges(indexes)
ranges.forEach { range ->
if (range.size > 2) {
stringFormat += "${dayFactory.dayFromInt(range.first())} to ${dayFactory.dayFromInt(range.last())},"
} else
range.forEach {
stringFormat += "${dayFactory.dayFromInt(it)},"
}
}
stringFormat = stringFormat.dropLast(1)
}
}
private fun splitIndexesToRanges(daysRange: List<Int>): ArrayList<List<Int>> {
val result = ArrayList<List<Int>>()
val slicePoint = ArrayList<Int>()
for (i in 0 until daysRange.size - 1) {
if (getTomorrow(daysRange[i]) != daysRange[i + 1]) {
slicePoint.add(i)
}
}
var start = 0
slicePoint.forEach {
result.add(daysRange.slice(start..it))
start = it + 1
}
result.add(daysRange.slice(start until daysRange.size))
return result
}
}
private fun isValidInput(seed: String): Boolean = true
fun main(args: Array<String>) {
val input = listOf(
"0,1,2,4,5,6",
"5,6,0",
"1,2,3,4"
)
input.forEach {
val dr = DaysRange(it)
println(dr)
}
}
示例輸出:
周日至周二、周四至周六
周五至周日
周一至周四

TA貢獻1799條經驗 獲得超6個贊
如果可以的話,我會堅持使用給定的時間 API(例如,java.time如果您使用 Java 8 或 joda-time 等)。以下解決方案也適用于您的enum,但您需要對其進行一些調整(即DayOfWeek具有getDisplayName并且還允許添加單日并始終獲得下一個連續天)。
我將工作分成 3 個獨立的任務。
將輸入讀入以下列表DayOfWeek:
fun readInput(input : String) : List<DayOfWeek> = input.splitToSequence(",")
.map(String::toInt)
.map {
/* your 0 is Sunday which is 7 for DayOfWeek; rest is the same */
if (it == 0) 7 else it
}
.map(DayOfWeek::of)
.toList()
也許您想添加.distinct().sorted()它或想事先驗證輸入...這取決于您真正想確保什么...
將星期幾轉換為連續天的列表:
fun List<DayOfWeek>.toDayRangeList() : List<DayRange> = fold(mutableListOf<DayRange>()) { consecutiveDaysList, day ->
consecutiveDaysList.apply {
lastOrNull()?.takeIf { it.to + 1 == day }?.apply {
to = day
} ?: add(DayRange(day))
}
}
為此,我還引入了一個DateRange-class 以便輕松改變結束日期...您也可以使用不可變對象執行此操作,但我發現這種方式更容易。它還DateRange包括一些輔助方法,可以輕松獲取所需形式的實際日期(在我的示例中FULL_STANDALONE):
data class DayRange(var from: DayOfWeek, var to: DayOfWeek = from) {
private fun DayOfWeek.toFullString(locale : Locale) = getDisplayName(TextStyle.FULL_STANDALONE, locale)
fun toString(locale : Locale) : String = when (from) {
// TODO add missing locale specific strings!
to -> from.toFullString(locale)
to + 1 -> "All day"
else -> "${from.toFullString(locale)} to ${to.toFullString(locale)}"
}
// just for convenience we use our custom toString-function:
override fun toString() = toString(Locale.getDefault())
}
可選地“展平”列表,即如果最后一天和第一天是連續的,則將它們合并到一個范圍中。當我們直接處理時,DayOfWeek我們可以簡單地添加另一天并比較兩天,無論其中一天是否是一周的最后一天:
fun List<DayRange>.flatten(): List<DayRange> {
if (size > 1) {
val first = first()
val last = last()
if (last.to + 1 == first.from)
return dropLast(1).drop(1)
.toMutableList()
.apply {
add(DayRange(last.from, first.to))
}
}
return this
}
將它們放在一起/演示:
listOf("1", "1,2", "1,0", "1,2,3", "1,2,4,5", "1,2,4,5,0", "1,2,3,4,5,6,0", "2,3,4,5,6,0,1")
.forEach { input ->
print(input)
readInput(input)
.toDayRangeList()
.flatten()
.joinToString(", ")
.also {
println("-> $it")
}
}
打印以下內容:
1 -> Monday
1,2 -> Monday to Tuesday
1,0 -> Sunday to Monday
1,2,3 -> Monday to Wednesday
1,2,4,5 -> Monday to Tuesday, Thursday to Friday
1,2,4,5,0 -> Thursday to Friday, Sunday to Tuesday
1,2,3,4,5,6,0 -> All day
2,3,4,5,6,0,1 -> All day
添加回答
舉報