Scala惯用的用分隔符拆分列表的方法是什么? [英] What's Scala's idiomatic way to split a List by separator?
问题描述
如果我有一个String类型的列表,
If I have a List of type String,
scala> val items = List("Apple","Banana","Orange","Tomato","Grapes","BREAK","Salt","Pepper","BREAK","Fish","Chicken","Beef")
items: List[java.lang.String] = List(Apple, Banana, Orange, Tomato, Grapes, BREAK, Salt, Pepper, BREAK, Fish, Chicken, Beef)
如何根据特定的字符串/模式(在本例中为"BREAK"
)将其分成 n
个单独的列表.
how can I split it into n
separate lists based on a certain string/pattern ("BREAK"
, in this case).
我已经考虑过使用 indexOf
查找"BREAK"
的位置,并以这种方式拆分列表,或者使用类似的方法使用 takeWhile(i => i!="BREAK")
,但我想知道是否有更好的方法?
I've thought about finding the position of "BREAK"
with indexOf
, and split up the list that way, or using a similar approach with takeWhile (i => i != "BREAK")
but I'm wondering if there's a better way?
如果有帮助,我知道 items
列表中将只有3套项目(因此有2个"BREAK"
标记).
If it helps, I know there will only ever be 3 sets of items in the items
list (thus 2 "BREAK"
markers).
推荐答案
def splitBySeparator[T](l: List[T], sep: T): List[List[T]] = {
l.span( _ != sep ) match {
case (hd, _ :: tl) => hd :: splitBySeparator(tl, sep)
case (hd, _) => List(hd)
}
}
val items = List("Apple","Banana","Orange","Tomato","Grapes","BREAK","Salt","Pepper","BREAK","Fish","Chicken","Beef")
splitBySeparator(items, "BREAK")
结果:
res1: List[List[String]] = List(List(Apple, Banana, Orange, Tomato, Grapes), List(Salt, Pepper), List(Fish, Chicken, Beef))
更新:以上版本虽然简洁有效,但存在两个问题:无法很好地处理边缘情况(如 List("BREAK")
或 List("BREAK","Apple","BREAK")
,并且不是尾部递归.因此,这是另一个(命令)版本,可解决此问题:
UPDATE: The above version, while concise and effective, has two problems: it does not handle well the edge cases (like List("BREAK")
or List("BREAK", "Apple", "BREAK")
, and is not tail recursive. So here is another (imperative) version that fixes this:
import collection.mutable.ListBuffer
def splitBySeparator[T](l: Seq[T], sep: T): Seq[Seq[T]] = {
val b = ListBuffer(ListBuffer[T]())
l foreach { e =>
if ( e == sep ) {
if ( !b.last.isEmpty ) b += ListBuffer[T]()
}
else b.last += e
}
b.map(_.toSeq)
}
它内部使用了一个 ListBuffer
,非常类似于我在 splitBySeparator
的第一版中使用的 List.span
的实现.
It internally uses a ListBuffer
, much like the implementation of List.span
that I used in the first version of splitBySeparator
.
这篇关于Scala惯用的用分隔符拆分列表的方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!