我们如何在Option [String]上映射/折叠?

时间:2018-10-31 19:15:46

标签: scala

我有一个类型为Option[String]的参数。我知道我们可以对其进行映射或折叠,从而得到String。我想在其他操作中使用String

我无法做到这一点。 你们能帮我举个例子吗?

4 个答案:

答案 0 :(得分:1)

如果您有Option[String],则有两种选择:

  1. 取出String
  2. Option内进行计算

要获取字符串,您可以使用模式匹配:

def printOption(parameter: Option[String]): Unit = 
  parameter match {
    case None => println("there was no string")
    case Some(theString) => println("the string was " + theString)
  }

或者您可以使用getOrElse

def getTheStringOrSmile(parameter: Option[String]): String =
  parameter.getOrElse(":)")

要在Option内进行计算,您可以使用高阶函数,例如mapflatMapforeachfilter等上。这些之所以称为“高阶函数”,是因为它们是具有参数的函数,这些参数本身就是函数。

例如,让我们看一下foreach,该函数具有从String(或Option中的任何内容)到Unit的功能。如果选项包含一个值,foreach将调用该函数。如果该选项不包含值,则不会发生任何事情。所以我们可以这样写:

def printOptionIfPresent1(parameter: Option[String]): Unit =
  parameter.foreach(theString => println("the string was " + theString))

语法theString => println("the string was " + theString)在这里构造一个函数。 theString是函数的参数,println("the string was " + theString)是函数的主体。

如果您在theString => ...语法中苦苦挣扎,也许printOptionIfPresent1的以下替代实现可以帮助您了解正在发生的事情:

class Helper$123 extends Function[String, Unit] {
  def apply(theString: String): Unit =
    println("the string was + theString)
}

def printOptionIfPresent2(parameter: Option[String]): Unit =
  parameter.foreach(new Helper$123)

当Scala编译器看到printOptionIfPresent1时,它或多或少将其转换为类似printOptionIfPresent1的形式,并为您生成正确的Helper$123类。

如果您希望发生某些事情(这里:打印到控制台),但是不想返回值,那么foreach方法是很好的。如果要返回值,请改用map方法。例如,要计算选项内字符串的长度,可以使用:

def optionalLength1(parameter: Option[String]): Option[Int] =
  parameter.map(theString => theString.length)

如果参数也是None,它也会返回None。如果您只想返回Int并在参数为0的情况下使用None,则可以添加getOrElse来取出Int

def optionalLength2(parameter: Option[String]): Int =
  parameter.map(theString => theString.length).getOrElse(0)

希望这为您提供了一个开始,但请确保也探索filterflatMap

答案 1 :(得分:1)

是的,您可以在scala中的mapfoldOption。为了简单起见,我们假设Option是专门的List,其中只有一个条目或没有条目。

要访问内容,我们有很多选择。最简单的方法是使用get进行检索。但是正如您所说,您想使用mapfold。因此,我们需要首先了解这些功能。

让我们从fold开始。一般来说,fold有两种:foldLeftfoldRightfoldLeft将从集合的开头开始执行某项任务,而foldRight则以相反的顺序执行。无论如何,都有两个参数列表。第一个包含起始值,第二个包含在每个元素上执行的功能。该函数必须使用两个参数累加器,它们将通过迭代和当前元素传递。该函数的结果必须适合下一个迭代累加器。累加器的类型是从起始值推断出来的。折叠操作的结果将始终与起始值相同。

// Adds all numbers in the list
List(1,2,3,4).foldLeft(0)((accumulator, element) => accumulator += element)
>res0: Int = 10
// Same as above method, but shortened with syntactic sugar
List(1,2,3,4).foldLeft(0)(_ + _)
>res1: Int = 10
// will also add all elements, but with an offset of 5
List(1,2,3,4).foldLeft(5)(_ + _)
>res2: Int = 15

现在让我们继续进行map。此函数遍历所有元素,并使用提供的功能对其进行修改。结果将是相同的集合类型,并以函数结果的类型键入。

// multiplies each element by 2
List(1,2,3,4).map(element => element * 2)
>res0: List[Int] = List(2,4,6,8)
// the same as above, but shortened with syntactic sugar
List(1,2,3,4).map(_ * 2)
>res1: List[Int] = List(2,4,6,8)

如果我们将此知识应用于Option,则可以按以下方式使用它:

// multiply contents by 2
List(5).map(_ * 2)
>res0: List[Int] = List(10)
Some(5).map(_ * 2)
>res1: Option[Int] = Some(10)

// multiply empty content by 2
val empty: Option[Int] = None // None cannot be typed
empty.map(_ * 2)
>res2: Option[Int] = None
List[Int]().map(_ * 2)
>res3: List[Int] = List()

如您所见,访问map函数内部的元素很简单。另外,由于NullPointerException仅对非空集合进行求值,因此您不受map的保护。

答案 2 :(得分:0)

要从String获取Option[String]的值,请使用getOrElse并指定默认值,以防OptionNone

val str = strOption.getOrElse("default")

如果您想先进行一些处理,请使用map

val str = strOption.map(_.drop(1)).getOrElse("default")

如果要执行一些返回不同类型的处理,请使用fold

val strLen = strOption.fold(0)(_.length)

请注意,在这种情况下,默认值位于计算之前。

答案 3 :(得分:-2)

您可以这样做。

val strOption :Option[String] = Some("test")

val str :String = strOption.getOrElse("")
print(str) // test

或者您可以这样做。

// your logic inside the function

def otherOperation(inputStr:String):
    println(inputStr)

strOption.map(str :String => otherOpration(str))

这是获得str的方式,您可以在任何需要的地方使用它。其中otherOperation是要使用该str的函数。