scala 如何使用高阶函数展平选项列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2895069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:10:41  来源:igfitidea点击:

How to flatten list of options using higher order functions?

scalascala-option

提问by Synesso

Using Scala 2.7.7:

使用 Scala 2.7.7:

If I have a list of Options, I can flatten them using a for-comprehension:

如果我有一个选项列表,我可以使用 for-comprehension 将它们展平:

val listOfOptions = List(None, Some("hi"), None)
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None)

scala> for (opt <- listOfOptions; string <- opt) yield string
res0: List[java.lang.String] = List(hi)

I don't like this style, and would rather use a HOF. This attempt is too verbose to be acceptable:

我不喜欢这种风格,宁愿使用 HOF。这种尝试过于冗长,无法接受:

scala> listOfOptions.flatMap(opt => if (opt.isDefined) Some(opt.get) else None)
res1: List[java.lang.String] = List(hi)

Intuitively I would have expected the following to work, but it doesn't:

直觉上,我本希望以下内容有效,但事实并非如此:

scala> List.flatten(listOfOptions)
<console>:6: error: type mismatch;
 found   : List[Option[java.lang.String]]
 required: List[List[?]]
       List.flatten(listOfOptions)

Even the following seems like it should work, but doesn't:

即使以下似乎也应该工作,但没有:

scala> listOfOptions.flatMap(_: Option[String])
<console>:6: error: type mismatch;
 found   : Option[String]
 required: (Option[java.lang.String]) => Iterable[?]
       listOfOptions.flatMap(_: Option[String])
                          ^

The best I can come up with is:

我能想到的最好的是:

scala> listOfOptions.flatMap(_.toList)         
res2: List[java.lang.String] = List(hi)

... but I would much rather not have to convert the option to a list. That seems clunky.

...但我宁愿不必将选项转换为列表。那看起来很笨重。

Any advice?

有什么建议吗?

回答by Arjan Blokzijl

In Scala 2.8, flatten will work:

在 Scala 2.8 中,flatten 将起作用:


Welcome to Scala version 2.8.0.RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val listOfOptions = List(None, Some("hi"), None)
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None)

scala> listOfOptions flatten
res0: List[java.lang.String] = List(hi)

This doesn't work in 2.7.7, however:

但是,这在 2.7.7 中不起作用:


Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).

scala> val listOfOptions = List(None, Some("hi"), None)
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None)

scala> listOfOptions.flatten
:6: error: no implicit argument matching parameter type (Option[java.lang.String]) => Iterable[Nothing] was found.
       listOfOptions.flatten

The collections library has been redesigned, and has improved a lot in 2.8, so perhaps you might want to try to use the latest Scala 2.8 RC and see if that makes it more easy to use for you.

集合库已经过重新设计,并在 2.8 中得到了很大改进,所以也许您可能想尝试使用最新的 Scala 2.8 RC,看看它是否使您更容易使用。

If you really don't want to use the toList method, I guess you can also write it like this:

如果你真的不想使用 toList 方法,我猜你也可以这样写:


scala> listOfOptions.flatMap(o => o)
res: List[java.lang.String] = List(hi)

Also not a thing of beauty perhaps, but at least this works in 2.7.7.

也许也不是什么美事,但至少这在 2.7.7 中有效。

回答by retronym

To complement Arjan's answer, in Scala 2.7.7 you can use List#flatten, but you need to help out the type inferencer:

为了补充 Arjan 的答案,在 Scala 2.7.7 中您可以使用List#flatten,但您需要帮助类型推断器:

Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val listOfOptions = List(None, Some("hi"), None)
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None)

scala> listOfOptions.flatten[String]                   
res0: List[String] = List(hi)

scala> val x: List[String] = listOfOptions.flatten
x: List[String] = List(hi)