首先,你的列表中每个字符串都包含了行首的空格。
这是你代码中最大的问题,有两种方法可以解决它。
要么修剪行(即去除行首和行尾的空格)...
val list1 =
"""992
1010
...
1306
1469""".lines.map(_.trim).toList
你可以在每行之前使用|
并使用stripMargin
,以便更好地阅读。
然后只需简单地应用takeWhile
/dropWhile
即可。
list1.takeWhile("BEGIN" !=) ++ list1.dropWhile("END"!=).tail
更高效地实现:
val (begin,middle) = list1.span("BEGIN" !=)
val end = middle.dropWhile("END" !=).tail
begin ++ end
编辑
我的解决方案本末倒置,会筛选掉(过滤掉)在BEGIN
和END
之间的值。为保留它们:
list1.dropWhile("BEGIN" !=).tail.takeWhile("END"!=)
编辑2
在此应对挑战...我将允许有多个BEGIN/END块,但也要考虑到输入可能格式不正确。如果有一个BEGIN没有相应的END会怎么样?也许有两个连续的BEGIN,或者在没有END的情况下列表结束了。
定义一些规则:
- 没有相应BEGIN的END将被忽略
- BEGIN/END块不嵌套
- 当已经在一个块中遇到BEGIN时,开始一个新块
- 如果在块中列表用完,则假定有一个隐含的END
话不多说,首先创建一个迭代器来识别输入中的每个"BEGIN"
:
val blocksStarts =
Iterator.iterate(list1)(_.dropWhile("BEGIN" !=).drop(1)).drop(1).takeWhile(Nil !=)
提供一个以"BEGIN"
开头的列表迭代器:
然后从这些列表中取出元素,直到达到相应的"END"
,或者遇到另一个"BEGIN"
,或者列表耗尽为止:
val blocks = blockStarts map {
_.takeWhile(x => x != "BEGIN" && x != "END")
} toList
最后的
toList
是因为此时它仍然是一个
Iterator
。现在您有了一个列表,每个列表对应于“块”中的一批元素,如先前规定的那样。
var flag = false
放在filter
块内部。这样就不会那么糟糕了。 - DebilskiBEGIN
...END
序列? - Ken BloomBEGIN
和END
之间的元素,那么“filter out”这个措辞真的很糟糕。 - Daniel C. Sobral