我需要在数组中找到第一个't'
符号。由于我们在 scala 中没有i++
左右,我最终写了以下内容:
val data: Array[Byte] = //..
var i = 0
while(i < data.length && data{val j = i; i += 1; j} != 't'){ }
我们可以以更整洁的方式重构它吗?
如果你想在满足条件之前做某事,你最好将 while 和 for 循环分开。在 while 循环的声明中声明 for 循环是丑陋的,当它变得更复杂时可能无法预测。
另外,不要使用var
.在使用 Scala 时,最佳做法是尽可能保持所有内容不可变。
像这样的东西在技术上可以完成这项工作:
def iterateUntilByte(byte: Byte, array: Array[Byte]): Any = {
for(i <- array.indices) {
if(array(i) != byte) /* do something */ else return
}
}
[斯卡拉小提琴]
或者更精简的版本:
def iterateUntilByte(byte: Byte, array: Array[Byte]): Any = {
array.map(a => if(a != byte) /* do something */) // can be foreach if return type is Unit
}
[斯卡拉小提琴]
您可以修改上面的代码,以便在找到t
时执行任何您想做的事情,例如if(a == byte) {...} else {...}
(如果您只对t
条目感兴趣(。
不要使用var
(如果可能的话,在你的时间限制内;请注意,这总是可能的(。
不要使用return
(永远!阅读此内容(。
你也不应该写循环。当你第一次开始使用来自命令式语言的Scala时,这似乎很难,但总有更好的方法。尝试编写循环不是"scala方式",不是函数式编程。
您可以使用takeWhile
和foreach
来执行某些操作,直到满足某些条件。您可以使用find
获取与某些条件匹配的第一项。您可以使用indexOf
.您可以使用zipWithIndex
.您可以使用filter
.您可以使用foldLeft
、collect
、groupBy
,当然也可以使用map
。您可以使用这些的复杂组合。您可以使用递归来"提前返回"。你永远不需要"写一个循环"。
您最初的问题似乎是XY问题,但似乎val i = data.indexOf('t')
会这样做,除非数据不包含't'
,否则它将-1
。更多想法;
val i = data.indexOf('t') match {
case -1 => data.length-1
case n => n
}
val i = Some(data.indexOf('t')).filterNot(_ == -1).getOrElse(data.length-1)
def i2(data: Array[Byte]): Array[Byte] = data.takeWhile(_ != 't')
def printUpToTab(data: Array[Byte]): Unit = i2(data).foreach(println)
// Warning: obtaining the index of something is not usually necessary.
// Step back and consider a cleaner solution.
def tabIndices(data: Array[Byte]): List[Int] = data.zipWithIndex.collect {
case ('t', n) =>
println(s"Found a tab at $n")
n
}.toList
// does a list contain less than N tab characters? Simple solution:
def containsLessThanNtabs(data: List[Byte], n: Int): Boolean =
data.count(_ == 't') < n
// This version will "return early" when N tabs are found,
// not counting through the entire list.
// This could be more efficient for very long lists.
// You must have a `List` to use the `::` construct.
def recursiveVersion(data: List[Byte], n: Int): Boolean = {
def recurse(bytes: List[Byte], count: Int): Boolean =
if (count >= n) false
else {
bytes match {
case Nil => true
case 't' :: tail => recurse(tail, count+1)
case _ :: tail => recurse(tail, count)
}
}
recurse(data, 0)
}
希望这有帮助。如果您需要帮助将这些想法扩展到您的实际问题,请告诉我。