1

I need to get a range from string. ; - is a delimeter.

So, for example i have string "10;15;1" and i need to get range from 10 to 15(ignoring the last number).

Expecting result:

"10;15;1" -> 10..15

So i tryed to write this code. How can i improove it? it looks bad and innefective

val arr = "10;15;1".split(";").dropLast(1).map { it.toBigDecimal() }
val someRange = arr[0] .. arr[1]
2
  • Given the pretty specific requirements, I wouldn't say that's bad code at all.  Changes you might consider include seeing whether you could make fewer assumptions about the input format; and handling invalid input better.  Also, if the numbers will always be integers, then Int might be simpler than BigDecimal.  This looks too specific to be worth splitting out to a separate function, unless you can make it more general somehow. Commented May 26, 2021 at 21:35
  • The only thing I might suggest is instead of the lambda, putting map(String::toBigDecimal) so the code is more self-documenting without losing its conciseness. Commented May 27, 2021 at 0:12

2 Answers 2

2

If you don't care about validation, you could do this:

fun toRange(str: String): IntRange = str
    .split(";")
    .let { (a, b) -> a.toInt()..b.toInt() }

fun main() {
    println(toRange("10;15;1"))
}

Output:

10..15

If you want to be more paranoid:

fun toRange(str: String): IntRange {
    val split = str.split(";")
    require(split.size >= 2) { "str must contain two integers separated by ;" }

    val (a, b) = split

    return try {
        a.toInt()..b.toInt()
    } catch (e: NumberFormatException) {
        throw IllegalArgumentException("str values '$a' and/or '$b' are not integers", e)
    }
}

fun main() {
    try { println(toRange("oops")) } catch (e: IllegalArgumentException) { println(e.message) }
    try { println(toRange("foo;bar;baz")) } catch (e: IllegalArgumentException) { println(e.message) }
    println(toRange("10;15;1"))
}

Output:

str must contain two integers separated by ;
str values 'foo' and/or 'bar' are not integers
10..15
Sign up to request clarification or add additional context in comments.

Comments

0

The function is very specific so it must not exist in the standard library. I have nothing against the implementation although I can suggest alternatives using a Regex and returning a null value if the string is not well formed. But it uses regex.

fun rangeFrom(str: String) : ClosedRange<BigDecimal>? {
    val regex = """^(\d+);(\d+);\d+$""".toRegex()
    val result = regex.find(str)
    return result?.destructured?.let { (fst, snd) ->
        fst.toBigDecimal() .. snd.toBigDecimal()
    }
}

Or you can just update your function checking that the length of the list produced by split is >= 2 and directly using arr[0].toBigDecimal() .. arr[1].toBigDecimal but it is not very different.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.