您對「更清潔,更習慣」解決方案的期望當然有點模糊,因爲它爲主觀性留下了很大的空間。一般來說,我會考慮一個更爲慣用的尾遞歸更新例程,但如果您更熟悉非函數式編程風格,它可能不會更「乾淨」。我想出了這一點:
@tailrec
def update(arr:List[Char], replace:Char, replacement:Char, result:List[Char] = Nil):List[Char] = arr match {
case `replace` :: tail =>
update(tail, replace, replacement, replacement :: result)
case _ => result.reverse ::: arr
}
這需要內序列中的一個(假定List
更容易模式匹配,因爲陣列是平凡轉換爲列表),並替換replace
炭與replacement
遞歸。
然後可以使用地圖更新外序列,就像這樣:
col.map { x => update(x, '.', ch) }
另一種更可重複使用的替代方法是寫自己的mapUntil
,或使用其中一個是補充庫中實現(Scalaz可能有類似的東西)。我看起來想出了這樣的一個:
def mapUntil[T](input:List[T])(f:(T => Option[T])) = {
@tailrec
def inner(xs:List[T], result:List[T]):List[T] = xs match {
case Nil => Nil
case head :: tail => f(head) match {
case None => (head :: result).reverse ::: tail
case Some(x) => inner(tail, x :: result)
}
}
inner(input, Nil)
}
它做同樣作爲一個經常調用map
,但它一旦停止的傳遞函數返回None
,例如
mapUntil(List(1,2,3,4)) {
case x if x >= 3 => None
case x => Some(x-1)
}
會導致
List[Int] = List(0, 1, 3, 4)
如果你想看看Scalaz,this answer可能是一個良好的開端。
Array [String]?在我看來應該有Array [Char]。 –
就地更新要求嗎? – fresskoma
寫一個遞歸方法? – Ashalynd