Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala unFlatMap

I would like to perform something like unFlatMap. Lets say that I have stream:

Stream("|","A","d","a","m","|","J","o","h","n", ...)

Stream could be infinite. I would like to convert it to:

Stream("Adam", "John", ...)

Ofcourse it is only example. In general I would like to perform some operation on elements separated by delimiter, Generic signature would be:

def unFlatMap[B](isSeparator:A => Boolean)(group:Seq[A] => B):TraversableOnce[B]

How to do that in clean and memory efficient way?

like image 239
Matzz Avatar asked Aug 27 '26 21:08

Matzz


1 Answers

You could do something like this:

def groupStream[A, B](s: Stream[A])(isSeparator: A => Boolean)(group: Seq[A] => B): Stream[B] = 
  group(s.takeWhile(!isSeparator(_)).toList) #:: groupStream(s.dropWhile(!isSeparator(_)).drop(1))(isSeparator)(group)

Or if you want an easier to read but more verbose version:

def groupStream[A, B](s: Stream[A])(isSeparator: A => Boolean)(group: Seq[A] => B): Stream[B] = {
  def isNotSeparator(i: A): Boolean = ! isSeparator(i)

  def doGroupStream(s: Stream[A]): Stream[B] = 
    group(s.takeWhile(isNotSeparator).toList) #:: doGroupStream(s.dropWhile(isNotSeparator).drop(1))

  doGroupStream(s)
}

If you want a implicit method on Stream, you could also do

implicit class ImprovedStream[A](val s: Stream[A]) extends AnyVal {
    def groupStream[B](isSeparator: A => Boolean)(group: Seq[A] => B): Stream[B] = {
      def isNotSeparator(i: A): Boolean = ! isSeparator(i)

      def doGroupStream(st: Stream[A]): Stream[B] = 
        group(st.takeWhile(isNotSeparator).toList) #:: doGroupStream(st.dropWhile(isNotSeparator).drop(1))

      doGroupStream(s)
    }
}

Now, using your example:

val a = Stream("|" ,"A","d","a","m","|","J","o","h","n", "|", "M", "a", "r", "y", "|", "J", "o", "e")

val c = groupStream(a)(_ == "|")(_.mkString)

c.take(10).toList
//  List[String] = List("", Adam, John, Mary, Joe, "", "", "", "", "")

Using the implicit version:

val c = groupStream(a)(_ == "|")(_.mkString)
like image 152
Onilton Maciel Avatar answered Aug 30 '26 10:08

Onilton Maciel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!