for (String stock : allStocks) {
Quote quote = getQuote(...);
if (null == quoteLast) {
continue;
}
Price price = quote.getPrice();
if (null == price) {
continue;
}
}
我不一定需要逐行翻译,但我正在寻找“Scala方式”来处理这类问题。
答案 0 :(得分:28)
在这样的情况下,你不需要继续或易碎或类似的东西:选项和理解很好地完成了这个技巧,
val stocksWithPrices =
for {
stock <- allStocks
quote <- Option(getQuote(...))
price <- Option(quote.getPrice())
} yield (stock, quote, price);
答案 1 :(得分:9)
通常,您会尝试在开始之前通过过滤来避免这些情况:
val goodStocks = allStocks.view.
map(stock => (stock, stock.getQuote)).filter(_._2 != null).
map { case (stock, quote) => (stock,quote, quote.getPrice) }.filter(_._3 != null)
(此示例显示如果需要,您将如何携带部分结果)。我使用了一个视图,以便根据需要计算结果,而不是在每一步创建一堆新的集合。
实际上,你可能有引号和这样的返回选项 - 在StackOverflow上查看如何使用它们而不是null返回值的示例。
但是,无论如何,如果那种事情不能很好地工作(例如,因为你需要保留太多的中间结果,或者你依赖于更新可变变量而你想保持评估模式简单,所以你知道发生了什么事情),你不能以不同的,可能更强大的方式设想问题,那么你可以
import scala.util.control.Breaks._
for (stock <- allStocks) {
breakable {
val quote = getQuote(...)
if (quoteLast eq null) break;
...
}
}
breakable
构造指定了中断应该到达的位置。如果你在for循环之外放置breakable,它就像标准的Java风格中断一样。如果你把它放在里面,它就像continue
。
当然,如果您的条件非常少,则根本不需要继续;只需使用if语句的else。
答案 2 :(得分:7)
此处的控制结构可以非常惯用地映射到以下for
循环中,您的代码演示了Scala的for
循环的设计过滤类型。
for {stock <- allStocks.view
quote = getQuote(...)
if quoteLast != null
price = quote.getPrice
if null != price
}{
// whatever comes after all of the null tests
}
顺便说一句,Scala会自动将其解析为Rex Kerr解决方案的代码
val goodStocks = allStocks.view.
map(stock => (stock, stock.getQuote)).filter(_._2 != null).
map { case (stock, quote) => (stock,quote, quote.getPrice) }.filter(_._3 != null)
对于可能使用continue
的所有不同类型的更复杂流程,此解决方案可能不起作用,但它确实解决了许多常见问题。
答案 3 :(得分:3)
如果重点确实放在continue
而不是null
处理,那么只需定义一个内部方法(null
处理部分是scala中的另一个成语):
def handleStock(stock: String): Unit {
val quote = getQuote(...)
if (null == quoteLast) {
return
}
val price = quote.getPrice();
if (null == price) {
return
}
}
for (stock <- allStocks) {
handleStock(stock)
}
答案 4 :(得分:1)
最简单的方法是将跳过的代码嵌入到if
中,并具有反转意义。