Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala implementation of Haskell's groupBy

Tags:

haskell

scala

I'm looking for a Scala implementation of Haskell's groupBy.

The behavior should be like this:

isD :: Char -> Bool
isD c = elem c "123456789-_ "

groupBy (\a b -> isD a == isD b) "this is a line with 0123344334343434343434-343 3345"
["this"," ","is"," ","a"," ","line"," ","with"," 0123344334343434343434-343 3345"]

I tried the Scala groupBy function, however it only takes a function of one argument, instead of Haskell's 2. I also looked at partition, however it only returns a tuple.

The function I'm looking for should group each consecutive element matching a predicate.

like image 725
Sander Avatar asked Nov 24 '11 19:11

Sander


3 Answers

Questions like this seem to come up quite often, which is a good indication IMO that Rex Kerr's groupedWhile method should be included in the standard collections library. However if you don't want to copy / paste that into your project...

I like your recursive solution, but it doesn't actually output the right thing (i.e. Strings), so here's how I'd change it:

def groupBy(s: String)(f: (Char, Char) => Boolean): List[String] = s match {
  case "" => Nil
  case x => 
    val (same, rest) = x span (i => f(x.head, i))
    same :: groupBy(rest)(f)
}

Then, take your function and try it in the REPL:

val isD = (x: Char) => "123456789-_ " contains x
groupBy("this is a line with 0123344334343434343434-343 3345")(isD(_) == isD(_))

The result is a List[String], which is presumably what you really wanted.

like image 159
Luigi Plinge Avatar answered Sep 27 '22 21:09

Luigi Plinge


Used this for now, thanks to the answers:

def groupByS(eq: (Char,Char) => Boolean, list: List[Char]): List[List[Char]] = {
    list match {
    case head :: tail => {
      val newHead = head :: tail.takeWhile(eq(head,_))
      newHead :: groupByS(eq, tail.dropWhile(eq(head,_)))
    }
    case nil => List.empty
  }
}

this can probably be improved upon ;)

like image 40
Sander Avatar answered Sep 27 '22 22:09

Sander


It's surely can't be too difficult to translate the Haskell version into Scala. Here's the Haskell definition of groupBy. It uses span; I don't know offhand whether there's an equivalent to span in Scala or whether you'll need to translate the Haskell definition of span as well.

like image 24
dave4420 Avatar answered Sep 27 '22 23:09

dave4420