Как упростить это в Котлине - PullRequest
0 голосов
/ 22 мая 2019

Есть ли более короткий способ в Котлине написать следующий код:

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 ]

4 голосов
/ 22 мая 2019

По соображениям производительности, вы должны лучше хешировать, чем поиск

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 голос
/ 22 мая 2019

Может быть, не самый лучший способ:

Сначала я строю набор со всеми возможными сопоставлениями месяца для индексации. Я определяю списки и обрабатываю их с 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")
    }

Преимуществом такого подхода будет очень сжатое место, где вы инициализируете все значения - и только один раз.

Обновление:

Вы также можете преобразовать это в карту, как предложил Фрэнк Неблунг - это определенно ускорит поиск:

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")
}
0 голосов
/ 22 мая 2019

Я бы сделал это так:

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")
}
0 голосов
/ 22 мая 2019

Я думаю, что-то вроде этого будет работать (Примечание: для краткости я перечислил только 3 месяца для 2 языков. На самом деле для нескольких языков существует 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

}
0 голосов
/ 22 мая 2019

Я бы, вероятно, держал некоторые списки (или карты), содержащие ваши месячные тексты, и перебирал бы их, например:

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(), если вам не нравится обнуляемый тип.

0 голосов
/ 22 мая 2019

С массивом массивов:

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().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...