开始Scala 2.13
,List
现在随unfold
构建器一起提供,可以与List::span
:
// val list = List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)
List.unfold(list) {
case Nil => None
case rest => Some(rest.span(_ == rest.head))
}
// List[List[Symbol]] = List(List('a, 'a, 'a, 'a), List('b), List('c, 'c), List('a, 'a), List('d), List('e, 'e, 'e, 'e))
或者,与Scala 2.13
's Option#unless
builder 结合使用:
List.unfold(list) {
rest => Option.unless(rest.isEmpty)(rest.span(_ == rest.head))
}
细节:
- Unfold 使用一个内部状态,在我们的例子中用
list
to split初始化List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)
- 在每次迭代中,我们
span
为了找到包含相同符号的前缀的内部状态:l.span(_ == l.head)
这是在第一次迭代期间l.span(_ == 'a)
并给出(List('a, 'a, 'a, 'a),List('b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))
- 正如
unfold
预期的那样,元组的每个迭代的Option
第一部分是要添加到正在构建的列表中的新元素(此处List('a, 'a, 'a, 'a)
),其第二部分是内部状态的新值(此处List('b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)
),该跨度完全符合该要求。
- 我们不断迭代相同的步骤,直到内部列表为空,在这种情况下,我们
unfold
通过返回来告诉 ing 我们已经完成None
。