由于我们不能做 i++,所以如何编码看起来更整洁



我需要在数组中找到第一个'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方式",不是函数式编程。

您可以使用takeWhileforeach来执行某些操作,直到满足某些条件。您可以使用find获取与某些条件匹配的第一项。您可以使用indexOf.您可以使用zipWithIndex.您可以使用filter.您可以使用foldLeftcollectgroupBy,当然也可以使用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)
}

希望这有帮助。如果您需要帮助将这些想法扩展到您的实际问题,请告诉我。

最新更新