2013-10-29 40 views
4

方案成語 「做,直到」 採集更新

val col: IndexedSeq[Array[Char]] = for (i <- 1 to n) yield { 
    val x = for (j <- 1 to m) yield 'x' 
    x.toArray 
} 

這是一個相當簡單的字符矩陣。用於允許更新的toArray

var west = last.x - 1 
    while (west >= 0 && arr(last.y)(west) == '.') { 
     arr(last.y)(west) = ch; 
     west -= 1; 
    } 

這是更新所有.ch直到非點字符被發現。

通常情況下,更新直到停止條件滿足,步數未知。

什麼是它的慣用等價物?

結論

這是可行的,但代價是不值得的,很多性能是輸給了表現力的語法時集合允許更新。

+1

Array [String]?在我看來應該有Array [Char]。 –

+0

就地更新要求嗎? – fresskoma

+0

寫一個遞歸方法? – Ashalynd

回答

3

您對「更清潔,更習慣」解決方案的期望當然有點模糊,因爲它爲主觀性留下了很大的空間。一般來說,我會考慮一個更爲慣用的尾遞歸更新例程,但如果您更熟悉非函數式編程風格,它可能不會更「乾淨」。我想出了這一點:

@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可能是一個良好的開端。

+0

請注意,我剛剛寫了'mapUntil'實現,它可能包含隱藏的「禮物」(讀取:bug)。如果你打算在生產中使用它,我肯定會爲它做幾個單元測試;) – fresskoma

+0

我不知道你最後的評論是什麼。你能澄清嗎?我對一些具體的數據感興趣,關於'mapUntil'實際上有多慢,以及爲什麼你想在列表中使用'update'。 – fresskoma

2

x3ro的回答是正確的答案,尤其是,如果你關心性能或者將要在多個地方使用這個操作。我想添加簡單的解決方案,只使用您在API集合中找到的內容:

col.map { a => 
    val (l, r) = a.span(_ == '.') 
    l.map { 
    case '.' => ch 
    case x => x 
    } ++ r 
} 
+0

'span'而不是'takeWhile' /'dropWhile'組合? –

+0

@SethTisue我認爲有一種方法!當我去看時,我沒有找到它,我一直在尋找像splitWhile這樣的東西。編輯。 – wingedsubmariner

相關問題