如何在Scala中从for循环中获取单个元素?
如何在Scala中从for循环中获取单个元素?
就像这个问题:
假设代码是
def findFirst[T](objects: List[T]):T = { for (obj <- objects) { if (expensiveFunc(obj) != null) return /*???*/ Some(obj) } None }
如何在Scala中像这样从for循环中产生单个元素?
我不想使用原本问题中提出的find,我想知道如何使用for循环来实现。
* 更新 *
首先,感谢所有的评论,但我想我在问题中并不清楚。我希望得到像这样的东西:
val seven = for { x <- 1 to 10 if x == 7 } return x
但它无法编译。出现两个错误:
-方法定义外返回
-方法main有返回语句,需要结果类型
我知道在这种情况下使用find()更好,我只是在学习和探索语言。在使用多个迭代器的更复杂情况下,我认为使用for查找实际上可以很有用。
感谢评论者,我将开始发放赏金来弥补糟糕的提问方式:)
admin 更改状态以发布 2023年5月22日
如果你想使用使用循环语句的for
循环,它比.find
、.filter
等链式调用的语法更简洁,有一个不错的技巧。而不是迭代严格的集合如列表,迭代惰性集合如迭代器或流。如果你开始是用一个严格的集合,用例如.toIterator
使它变得惰性。
让我们看一个例子。
首先定义一个“吵闹”的整数,它将显示它何时被调用。
def noisyInt(i : Int) = () => { println("Getting %d!".format(i)); i }
现在让我们用一些这些填充列表:
val l = List(1, 2, 3, 4).map(noisyInt)
我们想查找第一个偶数的元素。
val r1 = for(e <- l; val v = e() ; if v % 2 == 0) yield v
上面的行导致:
Getting 1! Getting 2! Getting 3! Getting 4! r1: List[Int] = List(2, 4)
...意味着所有的元素都被访问了。考虑到结果列表包含所有偶数,这是有意义的。这次让我们迭代一个迭代器:
val r2 = (for(e <- l.toIterator; val v = e() ; if v % 2 == 0) yield v)
这样的结果是:
Getting 1! Getting 2! r2: Iterator[Int] = non-empty iterator
请注意,循环只执行到可以确定结果是空迭代器还是非空迭代器的那一点。
现在,要获取第一个结果,你只需要简单地调用r2.next
。
如果你想得到Option
类型的结果,使用如下:
if(r2.hasNext) Some(r2.next) else None
Edit 这个编码的第二个例子只是:
val seven = (for { x <- (1 to 10).toIterator if x == 7 } yield x).next
,当然,如果你要使用.next
,你应该确保始终至少有一个解决方案。或者,使用定义为所有Traversable
的headOption
,以获取Option[Int]
。