从电子邮件列表中我得到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
适合我们。
答案 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()
<^>
调用说:如果此列表为空,则返回右侧返回类型函数定义的类型的零。如果列表非空,请将函数应用于
值nel
是NonEmptyList
,我可以安全地调用head
和tail
,而不必担心它们会抛出异常。我的函数返回(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]
无论如何都不会给你带来太多好处,是吗?