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

时间:2017-11-22 23:19:05

标签: scala

我有一个像这样的Tuple-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
}

到目前为止一切顺利。现在问题是......

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

所需的最终输出是Thing的扩展列表。所以上面的例子理论上会产生(命令不重要):

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

3 个答案:

答案 0 :(得分:3)

我会使用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))

答案 1 :(得分:2)

foldLeft

怎么样?
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)
}

答案 2 :(得分:0)

由于已经有问题的答案,但是如果我们注意到返回类型是List[Product with Serializable],因为您尝试创建包含不相关的案例类的列表,并且它没有进入最佳实践。

<强>实施例

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]

例如:

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))