如何从scala中的for循环中生成单个元素?

fae*_*anj 17 scala

很像这个问题:

用于循环的早期退出的功能代码

说代码是

def findFirst[T](objects: List[T]):T = {
  for (obj <- objects) {
    if (expensiveFunc(obj) != null) return /*???*/ Some(obj)
  }
  None
}
Run Code Online (Sandbox Code Playgroud)

如何在scala中从for循环中生成单个元素?

我不想使用find,就像原始问题中提出的那样,我很好奇是否以及如何使用for循环实现它.

*更新*

首先,感谢所有评论,但我想我在问题中并不清楚.我正在为这样的事情拍摄:

val seven = for {
    x <- 1 to 10
    if x == 7
} return x
Run Code Online (Sandbox Code Playgroud)

那不编译.这两个错误是: - 返回外部方法定义 - 方法main有return语句; 需要结果类型

我知道在这种情况下find()会更好,我只是在学习和探索语言.在一个更复杂的情况下,有几个迭代器,我认为找到for实际上可以是有用的.

感谢评论者,我将开始赏金以弥补问题的糟糕结果:)

Phi*_*ppe 21

如果你想使用一个for回路,它采用了更好的语法比链式调用.find,.filter等等,有一个巧妙的花招.而不是迭代像列表这样的严格集合,而不是像迭代器或流这样的惰性集合.如果你从一个严格的集合开始,让它变得懒惰,例如.toIterator.

我们来看一个例子吧.

首先让我们定义一个"嘈杂"的int,它会告诉我们何时调用它

def noisyInt(i : Int) = () => { println("Getting %d!".format(i)); i }
Run Code Online (Sandbox Code Playgroud)

现在让我们填写一些列表:

val l = List(1, 2, 3, 4).map(noisyInt)
Run Code Online (Sandbox Code Playgroud)

我们想要寻找第一个均匀的元素.

val r1 = for(e <- l; val v = e() ; if v % 2 == 0) yield v
Run Code Online (Sandbox Code Playgroud)

以上行导致:

Getting 1!
Getting 2!
Getting 3!
Getting 4!
r1: List[Int] = List(2, 4)
Run Code Online (Sandbox Code Playgroud)

...意味着访问了所有元素.这是有道理的,因为结果列表包含所有偶数.让我们这次迭代一个迭代器:

val r2 = (for(e <- l.toIterator; val v = e() ; if v % 2 == 0) yield v)
Run Code Online (Sandbox Code Playgroud)

这导致:

Getting 1!
Getting 2!
r2: Iterator[Int] = non-empty iterator
Run Code Online (Sandbox Code Playgroud)

请注意,循环仅在可以确定结果是空的还是非空的迭代器时执行.

要获得第一个结果,您现在可以直接致电r2.next.

如果需要Option类型的结果,请使用:

if(r2.hasNext) Some(r2.next) else None
Run Code Online (Sandbox Code Playgroud)

编辑此编码中的第二个示例只是:

val seven = (for {
    x <- (1 to 10).toIterator
    if x == 7
} yield x).next
Run Code Online (Sandbox Code Playgroud)

...当然,如果您要使用,您应该确保始终至少有一个解决方案.next.或者,使用headOption,为所有Traversables 定义,以获得Option[Int].


dap*_*pek 18

您可以将列表转换为流,以便只有按需评估for循环包含的任何过滤器.但是,从流中产生的总是会返回一个流,而你想要的是我想要一个选项,因此,作为最后一步,你可以检查结果流是否至少有一个元素,并将其头部作为一个选项返回.headOption函数就是这样做的.

def findFirst[T](objects: List[T], expensiveFunc: T => Boolean): Option[T] =
    (for (obj <- objects.toStream if expensiveFunc(obj)) yield obj).headOption
Run Code Online (Sandbox Code Playgroud)