我可以映射一个列表并在Scala中同时展开它吗?

我可以映射一个列表并在Scala中同时展开它吗?,scala,Scala,我有一个元组2列表,如下所示: val stuff = List( ("!thing","value"), ("otherthing","value") ) val processed = stuff.map{ case (label, value) => if(label.startsWith("!")) BigThing(label.tail,value) // extends trait Thing else LittleThing(label,value

我有一个元组2列表,如下所示:

val stuff = List( ("!thing","value"), ("otherthing","value") )
val processed = stuff.map{ case (label, value) => 
  if(label.startsWith("!"))
    BigThing(label.tail,value) // extends trait Thing
  else
    LittleThing(label,value) . // extends trait Thing
}
我想跳过此列表,从以下内容创建对象:

val stuff = List( ("!thing","value"), ("otherthing","value") )
val processed = stuff.map{ case (label, value) => 
  if(label.startsWith("!"))
    BigThing(label.tail,value) // extends trait Thing
  else
    LittleThing(label,value) . // extends trait Thing
}
到目前为止还不错。现在的问题是

在映射这些元组时,如果标签以“!”开头,我还想创建一个
Bonus(label.tail)
对象(也扩展trait Thing),并将该对象添加到结果列表中。这意味着n个项目的输入列表可能会导致输出>n个项目的列表。对此,最精简的功能解决方案是什么

所需的最终输出是一个扩展的事物列表。因此,上述示例理论上会产生(订单不重要):


我会使用
flatMap
来实现这一点:

val processed = stuff.flatMap { case (label, value) =>
  if (label.startsWith("!"))
    List(BigThing(label.tail, value), Bonus(label.tail))
  else
    List(LittleThing(label, value))
}
结果:

List(BigThing(thing,value), Bonus(thing), LittleThing(otherthing,value))

折页怎么样

val processed = stuff.foldLeft(List.empty[Thing]) { case (list, (label, value)) =>
  if (label.startsWith("!")) {
    list ++ (BigThing(label.tail, value) :: Bonus(label.tail) :: Nil)
  } else list :+ LittleThing(label,value)
}

因为这个问题已经有了答案,但是如果我们注意到返回类型是
List[Product with Serializable]
,因为您试图创建一个包含不相关案例类的列表,而这不是最佳实践

Ex:

scala> val processed = stuff.flatMap { case (label, value) =>
     |   if (label.startsWith("!"))
     |     List(BigThing(label.tail, value), Bonus(label.tail))
     |   else
     |     List(LittleThing(label, value))
     | }
processed: List[Product with Serializable] = List(BigThing(thing,value), Bonus(thing), LittleThing(otherthing,value))
我们可以通过显式提供返回类型来删除它。因为我们返回的是不同案例类的列表,所以我们可以使用
Lis[Any]

Ex:

scala> trait Thing extends Product with Serializable
defined trait Thing

scala> case class BigThing(id: String, value: String) extends Thing
defined class BigThing

scala> case class Bonus(id: String) extends Thing
defined class Bonus

scala> case class LittleThing(id: String, value: String) extends Thing
defined class LittleThing

scala> val stuff = List( ("!thing","value"), ("otherthing","value") )
stuff: List[(String, String)] = List((!thing,value), (otherthing,value))

scala>  val result = stuff.flatMap { case (label, value) =>
     |         label match {
     |           case lable if label.startsWith("!") => List(BigThing(label.tail, value), Bonus(label.tail))
     |           case _ => List(LittleThing(label, value))
     |         }
     |       }
result: List[Thing] = List(BigThing(thing,value), Bonus(thing), LittleThing(otherthing,value))

这些类都扩展了trait
Thing
,将返回类型写为
List[Thing]
更有意义。为什么不在REPL中尝试一下,看看返回值是什么,而不指定类型检查这是最佳答案。实际上,下面的foldLeft答案对于我的特定用法更有效,但平面图通常是更好的答案。