如果列表不为空或返回空列表,则返回尾部

时间:2013-06-18 15:12:31

标签: scala

从电子邮件列表中我得到2个值:

  • 列表头部的选项
  • 其余的列表

在scala中对此进行编码的惯用方法是什么?到目前为止,我有:

val primaryEmail = emails.headOption
val conf = Map[String, Any](
  "email" -> primaryEmail,
  "additionalEmails" -> 
     primaryEmail.map(_ => emails.tail).getOrElse(List())
)

编辑:至于为什么有Any:我们使用GSON进行json序列化,并在内部将所有集合转换为java集合并将它们传递给jsonSerializationContext.serialize,它们将java.lang.Object作为论证,Any适合我们。

5 个答案:

答案 0 :(得分:17)

我可能只是drop第一个元素(如果您确定第一个元素始终是主电子邮件)。像这样:

val conf = Map[String, Any](
  "email" -> emails.headOption,
  "additionalEmails" -> emails.drop(1)
)

如果主电子邮件不在列表中(列表为空),则不会出现异常。

答案 1 :(得分:8)

了解 scalaz 。所有这些都可以通过一个电话获得:

val (primary, rest) =  list <^> (nel => some(nel.head) -> nel.tail)
val conf = Map("email" -> primary, "additionalEmails" -> rest)

演示:

scala> val list = List(1, 2, 3)
list: List[Int] = List(1, 2, 3)

如果非空

scala> val (primary, rest) =  list <^> (nel => some(nel.head) -> nel.tail)
primary: Option[Int] = Some(1)
rest: List[Int] = List(2, 3)

如果为空:

scala> val list = List.empty[Int]
list: List[Int] = List()

scala> val (primary, rest) =  list <^> (nel => some(nel.head) -> nel.tail)
primary: Option[Int] = None
rest: List[Int] = List()

这是如何工作的?

<^>调用说:如果此列表为空,则返回右侧返回类型函数定义的类型的。如果列表非空,请将函数应用于

nelNonEmptyList,我可以安全地调用headtail,而不必担心它们会抛出异常。我的函数返回(Option[A], List[A])

当然,对于任何(None, Nil)

只是A

答案 2 :(得分:1)

Map [String,Any]?你也可以写PHP ...; - )

这是另一种方式:

scala> def build( emails:Seq[String] ):Map[String,Any] =
 emails.headOption.map(
         (primary) => Map( "primary" -> Some(primary), "other" -> emails.tail )
   ).getOrElse( Map( "primary" -> None, "other" -> Nil ) )
build: (emails: Seq[String])Map[String,Any]

scala> build(Nil)
res2: Map[String,Any] = Map(primary -> None, other -> List())

scala> build( List("fred"))
res3: Map[String,Any] = Map(primary -> Some(fred), other -> List())

真的 - 我不喜欢整个方法 - 我会做这样的事情:

case class EmailTo( primary:String, other:Seq[String] );

object EmailTo {
    def apply( addrs:Seq[String] ):Option[EmailTo] = 
         addrs.headOption.map( (primary) => EmailTo( primary, addrs.tail ) )
}

答案 3 :(得分:1)

对于序列,您可以对它们进行模式匹配以获得头部,其余部分为

val lst1 = Seq("primary", "secondary", "other");
// ...
lst1 match {
  case Seq(primary, rest @ _*)  => println(primary + "/" + rest);
  case _                        => println("Error: list empty.");
}

如果你使用Scala的List,那就更好了:

val lst2 = List("primary", "secondary", "other");
// ...
lst2 match {
  case primary :: rest  => println(primary + "/" + rest);
  case Nil              => println("Error: list empty.");
}

另请参阅What is the idiomatic way to pattern match sequence comprehensions?Scala pattern matching on sequences other than Lists


就像鲁本一样,我强烈建议你不要使用Map[String,Any]或类似的结构。你扔掉了Scala的类型系统给你的一切。很容易得到非常难以追踪的错误。或许可以将其作为另一个问题 - 描述您现在使用Map[String,Any]的原因并询问如何改进它。

答案 4 :(得分:0)

我建议

(("email", "additionalEmail") zip emails.splitAt(1)).toMap

这会留下List中的第一封电子邮件,而不是Option,但Map[String, Product]无论如何都不会给你带来太多好处,是吗?

相关问题