[英]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 變成它不是的東西。 它對函數式結構的支持有限,但它不是一種函數式語言。 如果沒有可以輕松拆分為頭和尾的鏈表實現,這種代碼風格將總是低效和/或繁瑣。 您可以尋找這樣的實現,例如在Arrow或kotlinx.collections.immutable中。 后者具有帶優化subList()的ImmutableList
- 您可以將它與上面提供的解決方案一起使用,以避免創建列表鏈。
更新
事實上,Java stdlib 中的基本列表實現也提供了優化的subList()
: AbstractList.java 。 因此,上述僅使用asList()
的解決方案應該沒問題,至少在針對 JVM 時是這樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.