在Kotlin中,是否可以使用较短的方式编写以下代码:
private fun getMonth(monthText: String): Int {
var x = arrayOf("january", "february", "jumper").indexOf(monthText)
if (x >= 0)
return x
x = arrayOf("Januari", "Februari", "Maret").indexOf(monthText)
if (x >= 0)
return x
throw Exception("Not found")
}
我必须对多种语言重复进行数组搜索,并希望避免重复重复的代码。注意:返回值必须指示月份。
答案 0 :(得分:4)
出于性能方面的考虑,散列比搜索更好
private val monthByName = mapOf(
"january" to 0,
"february" to 1,
"jumper" to 2,
"Januari" to 0,
"Februari" to 1,
"Maret" to 2
)
private fun getMonth(monthText: String) = monthByName[monthText] ?: throw NoSuchElementException(monthText)
答案 1 :(得分:1)
也许不是最好的方法:
我首先构建一个包含月到索引的所有可能映射的集合。我定义列表并用mapIndexed
处理它们以获取索引值。之后,我将它们弄平,以便与Pair<String, Int>
val monthsToIndex by lazy {
val lists = listOf(
arrayOf("january", "february", "jumper"),
arrayOf("Januari", "Februari", "Maret")
);
lists.map { it.mapIndexed { i, s -> s to i } }.flatten().toSet()
};
搜索现在是该集合中的find
+空检查以引发异常:
private fun getMonth(monthText: String): Int {
return monthsToIndex.find { it.first == monthText }?.second ?: throw Exception("Not found")
}
这种方法的好处是可以在非常简洁的地方初始化所有值-只需初始化一次。
更新:
您还可以按照弗兰克·内布伦(Frank Neblung)的建议将其转换为地图-这肯定会加快搜索速度:
val monthsToIndex by lazy {
val lists = listOf(
arrayOf("january", "february", "jumper"),
arrayOf("Januari", "Februari", "Maret")
);
lists.map { it.mapIndexed { i, s -> s to i } }.flatten().toMap()
};
private fun getMonth(monthText: String): Int {
return monthsToIndex[monthText] ?: throw Exception("Not found")
}
答案 2 :(得分:0)
具有数组数组:
private fun getMonth(monthText: String): Int {
val array = arrayOf(
arrayOf("january", "february", "jumper"),
arrayOf("Januari", "Februari", "Maret")
)
val months = array.firstOrNull { it.contains(monthText) }
if (months != null) return months.indexOf(monthText)
throw Exception("Not found")
}
我能想到的唯一的低效率是,将对将找到monthText
的数组进行两次扫描:一次使用contains()
,然后一次使用indexOf()
。
答案 3 :(得分:0)
我可能会保存一些包含您月份文本的列表(或地图)并对其进行迭代,例如:
val englishMonths = sequenceOf("January", "February", "March" /*, ... */).mapIndexed { index, s -> s to index }.toMap()
val xxxMonths = sequenceOf("january", "february", "jumper"/*, ... */).mapIndexed { index, s -> s to index }.toMap()
// and all the other month mappings you need
也许您也想将它们放在适当的语言环境映射中。
然后您的实际函数将对其进行迭代:
fun getMonth(monthText : String) = sequenceOf(
// all the month lists that are relevant:
englishMonths, xxxMonths /*, ... */
)
.mapNotNull { it[monthText] }
.firstOrNull()
如果找不到匹配项,现在将返回null
。如果您不喜欢此处可以为空的类型,也可以只添加?: throw WhateverExceptionSuites()
。
答案 4 :(得分:0)
我认为类似的方法会起作用(注意:为简便起见,我只列出了2种语言的3个月。实际上,多种语言有12个月的时间):
private fun getMonth(monthText: String): Int {
var x = arrayOf("january", "february", "march", "jumper", "Januari", "Februari", "Maret").indexOf(monthText)
if (x < 0)
throw Exception("Month not found")
return (x % 12) + 1
}
答案 5 :(得分:0)
我会这样:
private fun getMonth(monthText: String): Int {
val a = arrayOf("january", "february", "jumper")
val b = arrayOf("Januari", "Februari", "Maret")
val result = a.zip(b)
.mapIndexed{idx, it -> if (it.first == monthText || it.second == monthText) idx else null }
.mapNotNull{it}.firstOrNull()
return result ?: throw Exception("Not found")
}