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
添加回答
举报