试试这个。
将列表的头部作为列表列表的第一个元素的第一个元素。如果条件成立,则将内容添加到第一个列表中。如果不是,则以当前条目作为第一个元素启动一个新列表。
内部列表和外部列表都以错误的顺序构造。所以反转外层列表的每个元素(带map),然后反转外层列表。
val xs = List(1, 1, 1, 2, 2, 3, 3, 3, 3)
val ys = List(1, 2, 3, 1, 4, 6, 5, 7, 8)
def method[A](lst: List[A], cond: (A, A) => Boolean): List[List[A]] = {
lst.tail.foldLeft(List(List(lst.head))) { (acc, e) =>
if (cond(acc.head.head, e))
(e :: acc.head) :: acc.tail
else List(e) :: acc
}.map(_.reverse).reverse
}
method(xs, { (a: Int, b: Int) => a == b })
//> res0: List[List[Int]] = List(List(1, 1, 1), List(2, 2), List(3, 3, 3, 3))
method(ys, { (a: Int, b: Int) => a < b })
//> res1: List[List[Int]] = List(List(1, 2, 3), List(1, 4, 6), List(5, 7, 8))
迭代器重载
def method[A](iter:Iterator[A], cond: (A, A) => Boolean): List[List[A]] = {
val h = iter.next
iter.foldLeft(List(List(h))) { (acc, e) =>
if (cond(acc.head.head, e))
(e :: acc.head) :: acc.tail
else List(e) :: acc
}.map(_.reverse).reverse
}
method(xs.toIterator, { (a: Int, b: Int) => a == b })
//> res0: List[List[Int]] = List(List(1, 1, 1), List(2, 2), List(3, 3, 3, 3))
method(ys.toIterator, { (a: Int, b: Int) => a < b })
//> res1: List[List[Int]] = List(List(1, 2, 3), List(1, 4, 6), List(5, 7, 8))
适用于列表、迭代器和任何可以遍历一次的东西的更通用版本(此处向@cmbaxter 提供一些想法):
def method[A, T <: TraversableOnce[A]](trav: T, cond: (A, A) => Boolean)
: List[List[A]] = {
trav.foldLeft(List(List.empty[A])) { (acc, e) =>
if (acc.head.isEmpty || !cond(acc.head.head, e)) List(e) :: acc
else (e :: acc.head) :: acc.tail
}.map(_.reverse).reverse
}