2017-08-17 58 views
4

我有以下的科特林功能:科特林 - 轉換while循環功能的風格

fun func(n: Int): Int { 

    var count = 1 

    var m = n 
    while(m != 1) { 

     m = if(m.isOdd()) 3 * m + 1 else m/2 

     count++ 
    } 

    return count 
} 

我想編寫一個「功能性」的風格,簡單的算法,使用科特林的運營商如地圖(),計數( ),等我能想出最接近的事是這樣的:

fun func(n: Int): Int { 

    return n.toList() 
      .map{ if(it.isOdd()) 3*it+1 else it/2 } 
      .takeWhile { it != 1 } 
      .count() 

} 

顯然,上面的代碼不會因爲地圖只執行一次的工作,但你得到什麼,我想實現的想法。

PS:toList()僅僅是一個擴展功能是一個int轉換爲包含INT列表:

fun Int.toList() = listOf(this) 
+0

雖然@hotkey可能提供了正確的答案,但我認爲我們都應該同意,您的原始代碼實際上具有更高的內存效率,並且不會導致創建包含潛在數千個元素的序列,以查明生成了多少元素。 – Strelok

+0

@Strelok這是一個很好的觀點。我在尋找的是一個解決方案,其中所有變量都是不可變的,而且熱鍵的答案能夠實現這一點。但是,如果有人知道如何做同樣的事情,但是「即時丟棄元素」(所以內存不是問題),請告訴我們。 – Tiago

回答

6

既然你不知道有多少項目會出現,你可以構造一個(可能其中每個項目是基於前一個計算無限)序列,然後用你的病情it != 1限制,並指望有多少項目有:

return generateSequence(n) { if (it.isOdd()) 3 * it + 1 else it/2 } 
     .takeWhile { it != 1 } 
     .count() 

這裏,generateSequence(n) { ... },構建了一個Sequence<Int>n爲它的第一個元素,下面的每個元素是通過作爲lambda傳遞的代碼來計算的(它是在前一個元素上調用的,並且只有在查詢另一個項目時,也就是懶惰地)。