如何从scala中的for循环返回生成的值?
在我的项目中,我们正在从Java迁移到Scala。我必须使用Java中的一个函数,该函数使用continue in for循环,并根据for循环中的if条件返回一个值,如下所示如何从scala中的for循环返回生成的值?,scala,Scala,在我的项目中,我们正在从Java迁移到Scala。我必须使用Java中的一个函数,该函数使用continue in for循环,并根据for循环中的if条件返回一个值,如下所示 private TSourceToken getBeforeToken(TSourceToken token) { TSourceTokenList tokens = token.container; int index = token.posinlist; for ( int i = index
private TSourceToken getBeforeToken(TSourceToken token) {
TSourceTokenList tokens = token.container;
int index = token.posinlist;
for ( int i = index - 1; i >= 0; i-- ) {
TSourceToken currentToken = tokens.get( i );
if ( currentToken.toString( ).trim( ).length( ) == 0 ) {
continue;
}
else {
return currentToken;
}
}
return token;
}
def getBeforeToken(token: TSourceToken): TSourceToken = {
val tokens = token.container
val index = token.posinlist
for { i <- index -1 to 0 by -1
currentToken = tokens.get(i)
if(currentToken.toString.trim.length != 0)
} yield currentToken
}
为了将其转换为Scala,我使用了Yield选项以过滤掉满足if表达式else条件的值,如下所示
private TSourceToken getBeforeToken(TSourceToken token) {
TSourceTokenList tokens = token.container;
int index = token.posinlist;
for ( int i = index - 1; i >= 0; i-- ) {
TSourceToken currentToken = tokens.get( i );
if ( currentToken.toString( ).trim( ).length( ) == 0 ) {
continue;
}
else {
return currentToken;
}
}
return token;
}
def getBeforeToken(token: TSourceToken): TSourceToken = {
val tokens = token.container
val index = token.posinlist
for { i <- index -1 to 0 by -1
currentToken = tokens.get(i)
if(currentToken.toString.trim.length != 0)
} yield currentToken
}
我知道从for循环及其内部条件收集所有值会产生一个集合:IndexedSeq&因此会产生错误消息。我想不出一个逻辑形式,因为它是在Java代码中编写的。
有人能告诉我如何在Scala中构建代码而不使用yield,并在满足else条件后中断for循环吗?Scala中没有java中那样的for循环。因为产量和循环不同。它只是flatMap、map和withFilter函数组合的语法糖。在scala中,最好不要使用return关键字。基于具有返回值和返回词的表达式的语言可能会破坏逻辑,而其他开发人员不能期望这样
在您的情况下,最好使用find按谓词查找某些集合中的特定元素:
def getBeforeToken(token: TSourceToken): TSourceToken = {
val tokens = token.container
val index = token.posinlist
(index - 1 to 0 by -1)
.find(i => tokens.get(i).toString.trim.length != 0)
.fold(token)(i => tokens.get(i))
}
您可以阅读很多有关Scala产量的信息。以下是一些不错的文章: 通过Scala文档。 通过Scala文档。 阿尔文·亚历山大 作者@Dario。 但我认为在Scala中这样做是错误的。Scala是一种函数式编程语言,您可以使用它的能力 假设TSourceToken是具有两个成员的case类:
case class TSourceToken(container: Seq[String], posinlist: Int)
您要从最后一个posinlist标记中选择不是空的最后一个标记。有很多方法可以实现这一点。我想到的一个方法是:
val tokens = TSourceToken(Seq("", " ", " \n ", "real token", "\t\t", " ", " \n\n ", "token to ignore"), 5)
val token = tokens.container.take(tokens.posinlist).filter(_.trim.nonEmpty).last
正如您所期望的,令牌将具有真实令牌。代码运行可以在找到。a for comprehension不是解决此问题的正确工具:它用于映射,而不是查找 对于只将java代码重新写入scala的直接重写,请使用while循环:
def getBeforeToken(token: TSourceToken): TSourceToken = {
val tokens = token.container
var i = index - 1
while (i >= 0) {
val currentToken = tokens.get(i)
if (currentToken.toString.trim.length != 0) return currentToken
i -= 1
}
token
}
但是,如果token.container是某个集合,您可能会编写它而不进行显式迭代:
def getBeforeToken(token: TSoruceToken): TSourceToken =
token.container.reverseIterator.collectFirst {
case t if t.toString.trim.length != 0 => t
}.getOrElse(token)
在迁移过程中,最好还是坚持第一个,在尝试提高scala代码质量之前,尽快完成几乎机械化的翻译。因此,在这种情况下,我们会发现只要打破第一个值的循环,条件就满足了吗?我的理解正确吗?@Metadata是的,它会找到第一个满意的令牌,或者使用传递给GetOrelse的默认值。我觉得这可能更容易反转,比如token.container.view.takeindex.reverse.find_u.toString.trim.nonEmpty.getOrElsetokenoh ok。。现在明白了。它是一个java迭代器。为什么不将它转换为Scala类型呢?