Let's start with the signature of our function
def groupSubseq[T](in: Seq[T])(p: (T, T) => Boolean): Seq[Seq[T]]
Here p is predicate we use before add item to the existing subseq or create new one
We are going to use foldLeft
def groupSubseq[T](in: Seq[T])(p: (T, T) => Boolean): Seq[Seq[T]] = in
.foldLeft(Seq.empty[Seq[T]])((seq, item) => seq match {
case Nil => Seq(Seq(item)) // processing first element
case currentSeq +: tail =>
if (p(currentSeq.head, item)) {
// new element satisfies the condition, add it to the subsequence
(item +: currentSeq) +: tail
} else {
// new element not satisfies the condition, start new subsequence
Seq(item) +: seq
}
})
Looks like we've done here. But let me explain ))... This post is a result of a few similar tasks I've faced recently.
Task 1
Find all the sequences of the same character in the given string and count number of the character in each sequence
def countChar(seq: String): Seq[Char, Int] = ???
val test1 = "aaabbaaaabbb"
countChar(test1)
//res0: List((a,3), (b,2), (a,4), (b,3))
Task 2
Count number of all the sequences of the same sign in the given sequence of Int
def countSign(seq: Set[Int]): Int = ???
val test1 = Seq(1, 2, 3, -3, -2, 6, 7, 8, 9, -3, -1, -6, 7)
countSign(test1)
//res0: 3
Using our recent invention we may solve it easily
def countChar(seq: String) =
groupSubseq(seq)(_ == _).map(seq => seq.head -> seq.length).reverse
countChar("aaabbaaacddddd")
// res0: Seq[(Char, Int)] = List((a,3), (b,2), (a,3), (c,1), (d,5))
def countSign(seq: Seq[Int]) = groupSubseq(seq)(_ * _ > 0).count(_.length > 2)
countSign(Seq(1, 2, 3, 4, -1, 1, -1, -2, -3, -4, 0, 0, 0))
// res1: Int = 2
I hope to see your pros and cons in the comments. Thanks for reading.
Top comments (0)