我意識到這是一個老問題,但我只是有類似的問題,我想解決它,而無需追加或預先準備任何東西,它會處理序列的最後一個元素以無縫方式。我想出的方法是slidingFoldLeft
。你必須把第一個元素作爲一個特殊情況來處理(就像其他人提到的那樣,對於大寫字母,這是一個特殊情況),但是對於序列的結尾,你可以像處理其他情況一樣處理它。下面是實現和一些愚蠢的例子:
def slidingFoldLeft[A, B] (seq: Seq[A], window: Int)(acc: B)(
f: (B, Seq[A]) => B): B = {
if (window > 0) {
val iter = seq.sliding(window)
iter.foldLeft(acc){
// Operate normally
case (acc, next) if iter.hasNext => f(acc, next)
// It's at the last <window> elements of the seq, handle current case and
// call recursively with smaller window
case (acc, next) =>
slidingFoldLeft(next.tail, window - 1)(f(acc, next))(f)
}
} else acc
}
def capitalizeAndQuestionIncredulously(s: String) =
slidingFoldLeft(s.toSeq, 2)("" + s(0).toUpper) {
// Normal iteration
case (acc, Seq(c1, c2)) if c1.isLetter && c2.isLetter => acc + c2.toLower
case (acc, Seq(_, c2)) if c2.isLetter => acc + c2.toUpper
case (acc, Seq(_, c2)) => acc + c2
// Last element of string
case (acc, Seq(c)) => acc + "?!"
}
def capitalizeAndInterruptAndQuestionIncredulously(s: String) =
slidingFoldLeft(s.toSeq, 3)("" + s(0).toUpper) {
// Normal iteration
case (acc, Seq(c1, c2, _)) if c1.isLetter && c2.isLetter => acc + c2.toLower
case (acc, Seq(_, c2, _)) if c2.isLetter => acc + c2.toUpper
case (acc, Seq(_, c2, _)) => acc + c2
// Last two elements of string
case (acc, Seq(c1, c2)) => acc + " (commercial break) " + c2
// Last element of string
case (acc, Seq(c)) => acc + "?!"
}
println(capitalizeAndQuestionIncredulously("hello my name is mAtthew"))
println(capitalizeAndInterruptAndQuestionIncredulously("hello my name is mAtthew"))
和輸出:
Hello My Name Is Matthew?!
Hello My Name Is Matthe (commercial break) w?!
有趣...您的具體的例子聽起來好像是一個狀態機將是適當的(你可以做那些簡潔scala?),如果你想要「滑動」的某些功能,那麼你也需要預測 - 這聽起來像一個解析器。這也意味着我不知道足以回答你的問題:)(從我讀過的微小的一點聽起來像一個類似迭代的模式可能會有幫助,所以你可能會考慮這一點,但我真的不知道)。 – Owen
或者可能的方式來說,它是你需要做第一個特例,因爲它*是一個特殊情況,即它將很好有一個代表字符串的開始,這使得這個聲音甚至更像是一個狀態機/解析器。 – Owen
我同意歐文:問題描述特殊情況下的第一個字符,所以代碼也需要。以下是我如何閱讀問題陳述:「如果(a)是第一個字符,或者(b)跟隨字母字符,則將每個字符都大寫」。第一個字符的行爲需要特別定義。 –