我有一个像这样的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") )
答案 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))