如何在Kotlin中简化

时间:2019-05-22 18:47:21

标签: kotlin

在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")

}

我必须对多种语言重复进行数组搜索,并希望避免重复重复的代码。注意:返回值必须指示月份。

6 个答案:

答案 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")
}