tôi đã có một nhu cầu tương tự, nhưng solution từ @oxbow_lakes không mất trong để giải thích tình hình khi danh sách chỉ có một phần tử hoặc thậm chí nếu danh sách chứa các phần tử không được lặp lại. Ngoài ra, giải pháp đó không cho vay tốt với một trình lặp vô hạn (nó muốn "xem" tất cả các phần tử trước khi nó mang lại cho bạn một kết quả).
Điều tôi cần là khả năng nhóm các phần tử tuần tự khớp với vị từ, nhưng cũng bao gồm các phần tử đơn (tôi luôn có thể lọc chúng ra nếu tôi không cần chúng).Tôi cần các nhóm đó được phân phối liên tục, mà không phải đợi cho bản lặp đầu tiên hoàn toàn được tiêu thụ trước khi chúng được sản xuất.
tôi đã đưa ra các phương pháp sau đây mà làm việc cho nhu cầu của tôi, và nghĩ rằng tôi nên chia sẻ:
implicit class IteratorEx[+A](itr: Iterator[A]) {
def groupWhen(p: (A, A) => Boolean): Iterator[List[A]] = new AbstractIterator[List[A]] {
val (it1, it2) = itr.duplicate
val ritr = new RewindableIterator(it1, 1)
override def hasNext = it2.hasNext
override def next() = {
val count = (ritr.rewind().sliding(2) takeWhile {
case Seq(a1, a2) => p(a1, a2)
case _ => false
}).length
(it2 take (count + 1)).toList
}
}
}
Ở trên là sử dụng một vài lớp helper:
abstract class AbstractIterator[A] extends Iterator[A]
/**
* Wraps a given iterator to add the ability to remember the last 'remember' values
* From any position the iterator can be rewound (can go back) at most 'remember' values,
* such that when calling 'next()' the memoized values will be provided as if they have not
* been iterated over before.
*/
class RewindableIterator[A](it: Iterator[A], remember: Int) extends Iterator[A] {
private var memory = List.empty[A]
private var memoryIndex = 0
override def next() = {
if (memoryIndex < memory.length) {
val next = memory(memoryIndex)
memoryIndex += 1
next
} else {
val next = it.next()
memory = memory :+ next
if (memory.length > remember)
memory = memory drop 1
memoryIndex = memory.length
next
}
}
def canRewind(n: Int) = memoryIndex - n >= 0
def rewind(n: Int) = {
require(memoryIndex - n >= 0, "Attempted to rewind past 'remember' limit")
memoryIndex -= n
this
}
def rewind() = {
memoryIndex = 0
this
}
override def hasNext = it.hasNext
}
Ví dụ sử dụng:
List(1,2,2,3,3,3,4,5,5).iterator.groupWhen(_ == _).toList
cung cấp: List(List(1), List(2, 2), List(3, 3, 3), List(4), List(5, 5))
Nếu bạn muốn lọc ra các yếu tố duy nhất, chỉ cần áp dụng một filter
hoặc withFilter
sau groupWhen
Stream.continually(Random.nextInt(100)).iterator
.groupWhen(_ + _ == 100).withFilter(_.length > 1).take(3).toList
cho: List(List(34, 66), List(87, 13), List(97, 3))
Hãy coi chừng rằng việc triển khai này sẽ làm giảm các phần tử mà vị từ trả về false. Sử dụng borice tốt hơn. –