2014-02-21 32 views
1

有沒有一種標準的方式來結合現有的Scala集合函數來實現以下功能?或者這已經在Scalaz等一些流行的擴展庫中定義了?Scala中是否存在「部分減少」功能?

def partialReduceLeft[T](elements: List[T], nextReduction: List[T] => (T, List[T])): List[T] = 
    if (elements == Nil) 
    Nil 
    else { 
    val (reduction, residual) = nextReduction(elements) 

    if (residual.length >= elements.length) 
     throw new Exception("Residual collection from nextReduction function must be smaller than its input collection.") 

    if (residual == Nil) 
     List(reduction) 
    else 
     reduction :: partialReduceLeft(residual, nextReduction) 
    } 

該函數接受一個集合並應用一個用戶定義的函數,該函數返回可能消耗一個或多個元素的第一個縮減。該方法一直持續到所有元素都被消耗完。

生成的集合可能與輸入集合的大小相等或更小(我寧願不科學地稱此爲「部分減少左邊」 - 因爲不知道此類標準函數的確切期限:))。

我的實現不是尾遞歸的,說實話,我寧願使用別人的代碼!

回答

4

斯卡拉也有類似的方法:unfold

您可以實現使用unfold這樣你的方法:

def partialReduceLeft[T](elements: List[T], 
         nextReduction: List[T] => (T, List[T])): Stream[T] = 
    unfold(elements){ es => es.nonEmpty option nextReduction(es) } 
+0

很有趣,我會考慮這個方法以後。乍看之下,展開似乎是雙重對立。這意味着要從一個元素創建一個集合(或者從一個集合中創建一個更大的集合)。但是,我正在做的是從一個集合中製作一個相同或更小的集合。那有意義嗎?我毫不懷疑它做你所說的!我只是說這個措辭看起來不直觀,或者僅僅是因爲你如何使用它?我現在沒有代碼在我面前:P –

+0

讀取簽名是有意義的:結果確實是一個集合,但不是A類(種子) - 而是它的類型B,它是您的類型減少功能產生A.良好的應用 - 謝謝! –

+1

@LawrenceWagerfield:另外,請看iteratee。這是'flatMap'的一種泛化。 – senia