假设我有以下内容:
case class Thing(num: Int)
val xs = List(Thing(1), Thing(2), Thing(3))
我想要做的是将列表分成一个特定的值,以及列表的其余部分。目标值可以位于列表中的任何位置,也可以根本不存在。在处理其他值之后,单个值需要单独处理,因此我不能简单地使用模式匹配。
到目前为止我所拥有的是:
val (targetList, rest) = xs.partition(_.num == 2)
val targetEl = targetList match {
case x :: Nil => x
case _ => null
}
是否可以将这两个步骤结合起来?像
val (targetEl, rest) = xs.<some_method>
关于处理订单的说明: 必须最后处理目标元素的原因是它用于HTML模板(Play框架)。循环其他元素,并为每个元素呈现HTML元素。在该组元素之后,为目标元素创建另一个HTML元素。
答案 0 :(得分:3)
你可以在map
中使用模式匹配来完成它,你需要多个案例:
xs map {
case t @ Thing(1) => // do something with thing 1
case t => // do something with the other things
}
处理OP的额外要求:
xs map {
case t @ Thing(num) if(num != 1) => // do something with things that are not "1"
case t => // do something with thing 1
}
答案 1 :(得分:1)
以下两个列表作为某些条件的元组。
case class Thing(num: Int)
val xs = List(Thing(1), Thing(2), Thing(3))
val partioned = xs.foldLeft((List.empty[Thing], List.empty[Thing]))((x, y) => y match {
case t @ Thing(1) => (x._1, t :: x._2)
case t => (t :: x._1, x._2)
})
//(List(Thing(3), Thing(2)),List(Thing(1)))
答案 2 :(得分:0)
试试这个:
val (targetEl, rest) = (xs.head, xs.tail)
适用于非空列表。无案件必须单独处理。
答案 3 :(得分:0)
经过一些实验,我想出了以下内容,这几乎就是我要找的内容:
rest map <some_method>
maybeTargetEl map <some_other_method>
目标值仍然包含在容器中,但至少它保证单个值。
之后我可以做
var (maybeTargetEl, rest) = xs.
foldLeft((Option.empty[Thing], ListBuffer[Thing]())){ case ((opt, lb), x) =>
if (x.num == 1)
(Some(x), ls)
else
(opt, lb += x)
} match {
case (opt, lb) => (opt, lb.toList)
}
如果原始列表的顺序很重要:
{{1}}
答案 4 :(得分:0)
@evanjdooner如果目标元素只出现一次,那么折叠的解决方案就有效。如果您只想提取一个目标元素:
def find(xs: List[T], target: T, prefix: List[T]) = xs match {
case target :: tail => (target, prefix ::: tail)
case other :: tail => find(tail, target, other :: prefix)
case Nil => throw new Exception("Not found")
}
val (el, rest) = find(xs, target, Nil)
抱歉,我无法将其添加为评论。