I swore I'd never ask for an "idiomatic way" of do...
# getting-started
v
I swore I'd never ask for an "idiomatic way" of doing something in Kotlin, but here goes... I'd like to build a Map<String,String> in a by lazy {...} block. I'm sure I should be doing something clever with zips or flatmaps or sequences or something, but I'm not that clever. Is there a more idiomatic way of doing this, without all the temporary variables?
Copy code
val pathParameters: Map<String, String> by lazy {
        val tmpMap = mutableMapOf<String, String>()
        val inputParts = apiRequest.path.split("/")
        val routeParts = pathPattern.split("/")
        for (i in routeParts.indices) {
            if (routeParts[i].startsWith("{") && routeParts[i].endsWith("}")) {
                val param = routeParts[i].removeSurrounding("{", "}")
                tmpMap[param] = inputParts[i]
            }
        }
        tmpMap.toMap()
    }
b
Copy code
val pathParameters: Map<String, String> by lazy {
    val tmpMap = mutableMapOf<String, String>()
    val inputParts = apiRequest.path.split("/")
    val routeParts = pathPattern.split("/")
    inputParts.zip(routeParts)
        .filter { pair -> pair.second.startsWith("{") && pair.second.endsWith("}") }
        .map { pair -> pair.second.substring(1..pair.second.length - 2) to pair.first }
        .toMap()
}
j
Copy code
"pathPattern".split("/").zip("apiRequest.path".split("/"))
        .filter { (routePart, _) -> routePart.startsWith("{") && routePart.endsWith("}") }
        .associate { (routePart, inputPart) -> routePart.removeSurrounding("{", "}") to inputPart }
j
When you're building a map "by hand" (without functional fanciness), note that you can still get rid of the temporary mutable map + toMap by using a
buildMap { .... }
call. This allows you to access the mutable map to conditionally put things into it, and outside of the builder you get the read-only
Map
type
­čĹŹ 2
e
by which Joffrey means something like this
Copy code
buildMap {
    val inputParts = ...
    val routeParts = ...
    for ((i, routePart) in routeParts.withIndex()) {
        if (routePart...) {
            val param = ...
            put(param, inputParts.getOrNull(i))
        }
    }
}
note that you can also use
withIndex
or
forEachIndexed
to iterate over items and their indices at the same time
v
Thank you all. I shall try them out in the morning and see what combination works before for me. I always prefer readable and explicit than clever code, but I sure there was a clever and readable solution to this.