我收到了多个逗号分隔的字符串整数作为输入,例如以下字符串:
- "5,6,0"
- "0,1,2">
- "1,2,3,4">
这些整数中的每一个都表示一周中的某一天
- 0 = 星期日 1 = 星期一 2 = 星期二 3 = 星期三 4 = 星期四 5 = 星期五 6 = 星期六
在第一个字符串的情况下,这意味着周四到周日第二个字符串在星期日至星期二有效 第三个字符串在星期一至星期四有效
目前,我正在使用以下内容
private fun mapOfDays(validDays: String): LinkedHashMap<Int, String>
{
if (!validDays.isBlank())
{
val daysArray = validDays.split("\s*,\s*") as Array<String>
var mapDays = LinkedHashMap<Int, String>()
var mapDay = LinkedHashMap<Int, String>()
mapDays[0] = "SUNDAY"
mapDays[1] = "MONDAY"
mapDays[2] = "TUESDAY"
mapDays[3] = "WEDNESDAY"
mapDays[4] = "THURSDAY"
mapDays[5] = "FRIDAY"
mapDays[6] = "SATURDAY"
for (day in daysArray)
{
if (mapDays.containsKey(day.toInt()))
{
mapDay[day.toInt()] = mapDays[day.toInt()]!!
}
}
return mapDay
}
return LinkedHashMap()
}
private fun mappedDays(mapOfDays: LinkedHashMap<Int, String>?): String
{
if (!mapOfDays.isNullOrEmpty())
{
val mapSize = mapOfDays.size
if (mapSize > 6) return "All Day"
if (mapSize > 5) return sixDayString(mapOfDays)
if (mapSize > 4) return fiveDayString(mapOfDays)
if (mapSize > 3) return fourDayString(mapOfDays)
if (mapSize > 2) return threeDayString(mapOfDays)
if (mapSize > 1) return twoDayString(mapOfDays)
if (mapSize > 0) return oneDayString(mapOfDays)
}
return ""
}
private fun twoDayString(mapOfDays: LinkedHashMap<Int, String>): String
{
val firstPosition: Int = mapOfDays.keys.toIntArray()[0]
val lastPosition: Int = mapOfDays.keys.toIntArray()[1]
val lastDay = Days.values()[lastPosition]
val firstDay = Days.values()[firstPosition]
return "$firstDay and $lastDay"
}
private fun oneDayString(mapOfDays: LinkedHashMap<Int, String>): String
{
var firstPosition: Int = mapOfDays.keys.toIntArray()[0]
val firstDay = Days.values()[firstPosition]
return "$firstDay"
}
private fun threeDayString(mapOfDays: LinkedHashMap<Int, String>): String
{
val firstPosition: Int = mapOfDays.keys.toIntArray()[0]
val secondPosition: Int = mapOfDays.keys.toIntArray()[1]
val thirdPosition: Int = mapOfDays.keys.toIntArray()[2]
val firstDay = Days.values()[firstPosition]
val secondDay = Days.values()[secondPosition]
val lastDay = Days.values()[thirdPosition]
return "$firstDay, $secondDay and $lastDay"
}
private fun fourDayString(mapOfDays: LinkedHashMap<Int, String>): String
{
val firstPosition: Int = mapOfDays.keys.toIntArray()[0]
val secondPosition: Int = mapOfDays.keys.toIntArray()[1]
val thirdPosition: Int = mapOfDays.keys.toIntArray()[2]
val fourthPosition: Int = mapOfDays.keys.toIntArray()[3]
val firstDay = Days.values()[firstPosition]
val secondDay = Days.values()[secondPosition]
val thirdDay = Days.values()[thirdPosition]
val lastDay = Days.values()[fourthPosition]
return "$firstDay, $secondDay, $thirdDay and $lastDay"
}
private fun fiveDayString(mapOfDays: LinkedHashMap<Int, String>): String
{
val firstPosition: Int = mapOfDays.keys.toIntArray()[0]
val secondPosition: Int = mapOfDays.keys.toIntArray()[1]
val thirdPosition: Int = mapOfDays.keys.toIntArray()[2]
val fourthPosition: Int = mapOfDays.keys.toIntArray()[3]
val fifthPosition: Int = mapOfDays.keys.toIntArray()[4]
val firstDay = Days.values()[firstPosition]
val secondDay = Days.values()[secondPosition]
val thirdDay = Days.values()[thirdPosition]
val fourthDay = Days.values()[fourthPosition]
val lastDay = Days.values()[fifthPosition]
return "$firstDay, $secondDay, $thirdDay, $fourthDay and $lastDay"
}
private fun sixDayString(mapOfDays: LinkedHashMap<Int, String>): String
{
var firstPosition: Int = mapOfDays.keys.toIntArray()[0]
var lastPosition: Int = 0
for (day in mapOfDays.keys)
{
lastPosition = day
}
val lastDay = Days.values()[lastPosition]
val firstDay = Days.values()[firstPosition]
return "$firstDay to $lastDay"
}
}
enum class Days()
{
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
但是,我当前的实现能够告诉我包括哪些天,并且无法绘制出天数组,例如:
如果我得到"0,1,3,4,5,6" 我想要的最终字符串输出如下:周三至周一
或
"0,1,3,4,5"将导致以下结果:星期日,星期一,星期三到星期五。
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)
}
}
示例输出:
周日至周二,周四至周六
周五至周日
周一至周四
如果可以的话,我会坚持使用给定的时间 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
类,以便轻松更改结束日期......您也可以使用不可变对象执行此操作,但我发现这种方式更容易。该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