簡體   English   中英

如何切片 vararg 參數

[英]How to slice vararg argument

我寫了一個擴展 function 以通過其名稱獲取 JSON object 的元素:

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參數參數的最佳方法是什么?

為什么不嘗試遍歷所有對象並獲取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
}

我們只能在 public function 中使用 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()都不復制數據,而只是包裝現有集合。 盡管如此,這仍然遠非理想,因為它為每次迭代創建一個新的 object 並且它可能創建一個視圖鏈(它取決於subList()的內部實現)。 或者,內部 function 可以接收一個數組和偏移量——這將解決上述兩個問題。

一般來說,我建議不要嘗試將 Kotlin 變成它不是的東西。 它對函數式結構的支持有限,但它不是一種函數式語言。 如果沒有可以輕松拆分為頭和尾的鏈表實現,這種代碼風格將總是低效和/或繁瑣。 您可以尋找這樣的實現,例如在Arrowkotlinx.collections.immutable中。 后者具有帶優化subList()ImmutableList - 您可以將它與上面提供的解決方案一起使用,以避免創建列表鏈。

更新

事實上,Java stdlib 中的基本列表實現也提供了優化的subList()AbstractList.java 因此,上述僅使用asList()的解決方案應該沒問題,至少在針對 JVM 時是這樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM