kotlin 如何分割vararg参数

vnzz0bqm  于 2022-11-25  发布在  Kotlin
关注(0)|答案(2)|浏览(172)

我编写了一个扩展函数,通过名称获取JSON对象的元素:

fun JSONObject.obj (name: String): JSONObject? =
    try { this.getJSONObject(name) }
    catch (e: JSONException) { null }

现在,我想将其扩展到嵌套的JSON对象。

tailrec fun JSONObject.obj (first: String, vararg rest: String): JSONObject? =
    if (rest.size == 0)
        obj(first)
    else
        obj(first)?.obj(rest[0], *rest.drop(1).toTypedArray())

但在我看来,这是相当低效的。
分割vararg参数的最佳方法是什么?

whlutmcx

whlutmcx1#

我们只能在公共函数中使用vararg,但在内部使用list进行递归:

fun JSONObject.obj (first: String, vararg rest: String): JSONObject? = obj(first, rest.asList())

private tailrec fun JSONObject.obj (first: String, rest: List<String>): JSONObject? =
    if (rest.size == 0)
        obj(first)
    else
        obj(first)?.obj(rest[0], rest.subList(1, rest.size))

asList()subList()都不复制数据,而只是 Package 现有的集合。尽管如此,这还远远不够理想,因为它为每次迭代创建一个新对象,并可能创建一个视图链(这取决于subList()的内部实现)。或者,内部函数可以接收一个数组和偏移量-这将解决上述两个问题。
一般来说,我建议不要试图把Kotlin变成它不是的东西。它对函数结构的支持有限,但它不是一种函数语言。如果没有链表实现,它可以很容易地被分成头和尾,这种风格的代码将总是低效和/或麻烦的。你可以寻找这样的实现,例如在Arrowkotlinx.collections.immutable中,后者包含带有优化subList()的ImmutableList-您可以将其与上面提供的解决方案一起使用,以避免创建列表链。

更新

事实上,Java stdlib中的基本列表实现还提供了优化的subList():因此,上面的解决方案只使用asList()就可以了,至少在以JVM为目标时是这样。

jgwigjjp

jgwigjjp2#

与切片不同,为什么不尝试遍历所有对象并得到JSONObject?我认为这会更有效。

fun JSONObject.obj(vararg names: String): JSONObject? {
    var jsonObject = this
    for (name in names) {
        if (!jsonObject.has(name))
            return null
        jsonObject = jsonObject.getJSONObject(name)
    }
    return jsonObject
}

相关问题