我在一次采訪中被問到這個問題。她想要scala而不是java的答案。我的回答是以 java 為中心的。請注意,您不能使用字符索引來決定是大寫還是小寫。你能找到一種更好的方法讓它以 scala 為中心嗎?我想不出任何可以在這里提供幫助的 StringOps 內置函式。專注于消除對 var 的需求。我使用尾遞回(之后)重寫了它,但答案效率低下,所以我堅持使用這個以 java 為中心的答案。
object Cap extends App {
def _capitalizeEveryOtherLetter(str: String): String = {
val s2: Array[Char] = str.toCharArray
var capitalize: Boolean = true
val arr: Array[Char] = (for (c <- s2) yield {
if (!Character.isLetter(c)) {
c
} else if (capitalize) {
capitalize = false
val newChar = Character.toUpperCase(c)
newChar
} else {
capitalize = true
val newChar = Character.toLowerCase(c)
newChar
}
})
new String(arr)
}
val s1: String = "*7yTuu(i&^giuisKJSU&Y"
println(s"${_capitalizeEveryOtherLetter(s1)}")
}
預期的輸出是
*7YtUu(I&^gIuIsKjSu&Y
與如何將字串中的所有其他字符轉換為大寫字母類似但不同,因為它依賴于對這個問題無效的索引。
uj5u.com熱心網友回復:
如果你只有字母,scala 方式就像
input.grouped(2).map(_.capitalize).mkString("")
跳過非字母字符會稍微復雜一些:首先弄清楚每個字母應該如何轉換,然后替換它們:
val letters = input.filter(_.isLetter).grouped(2).flatMap(_.capitalize)
input.map { c => if (c.isLetter) letters.next else c }
但這對于面試來說可能太“聰明”了:)(嗯,取決于你在哪里面試)。
“使用狀態遍歷/轉換”的“官方”scala 方法是(尾)遞回或(對于更簡單的情況)foldLeft使用累加器。避免可變性和將東西附加到另一個答案中提到的字串或集合的低效率的技巧是向后構建一個串列,并最終將其反轉。
input.foldLeft[(Boolean, List[Char])](true -> Nil) {
case ((x, ac), c) if !c.isLetter => (x, c::ac)
case ((true, ac), c) => (false, c.toUpper :: ac)
case ((_, ac), c) => (true, c :: ac)
}._2.reverse.mkString("")
由于您的問題被標記為tail-recursion,因此這是一種尾遞回方式(與上面的 foldLeft 并沒有什么不同):
@tailrec
def upSome(
chars: List[Char],
state: Boolean = true,
result: List[Char]
): List[Char] = (state, chars) match {
case (_, Nil) => result.reverse
case (_, c::tail) if !c.isLetter => upSome(tail, state, c::result)
case (true, c::tail) => upSome(tail, false, c::result)
case (_, c::tail) => upSome(tail, true, c::result)
}
你會用它作為
upSome(input.toList).mkString("")
uj5u.com熱心網友回復:
由于字串操作很昂貴,我只會使用 aStringBuilder和 afoldLeft
def capitalizeEveryOtherLetter(str: String): String = {
val sb = new StringBuilder(str.size)
str.foldLeft(false) {
case (flag, char) =>
val isLetter = char.isLetter
if (isLetter && flag) {
sb = char.toUpper
false
} else {
sb = char.toLower
isLetter || flag
}
}
sb.result()
}
您可以看到這里運行的代碼。
uj5u.com熱心網友回復:
另一個(更實用?)一個,它回避了保持“我們是小寫還是大寫”狀態的需要:
val xs = "the quick brown fox jumps over the lazy dog";
val fs =
LazyList.continually(LazyList((c:Char) =>c.toUpper, (c:Char)=>c.toLower)).flatten;
(xs zip fs).map{case (c, f) => f(c)}.mkString
不過,我可能誤解了問題的意圖——這會交替大寫和小寫,而不管它是否是字母。我離開它是因為它是一種有趣的替代方法
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/480335.html
