Scala实现了Haskell的groupBy

时间:2011-11-24 19:16:37

标签: scala haskell

我正在寻找Haskell的groupBy的Scala实现。

行为应该是这样的:

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"]

我尝试了Scala groupBy函数,但它只需要一个参数的函数,而不是Haskell的2.我也查看了分区,但它只返回一个元组。

我正在寻找的函数应该对每个与谓词匹配的连续元素进行分组。

4 个答案:

答案 0 :(得分:2)

这样的问题似乎经常出现,这是一个很好的迹象IMO,Rex Kerr的groupedWhile方法应该包含在标准集合库中。但是,如果您不想将其复制/粘贴到项目中......

我喜欢你的递归解决方案,但它实际上并没有输出正确的东西(即字符串),所以这就是我改变它的方式:

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)
}

然后,接受你的功能并在REPL中尝试:

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

结果是List[String],大概是你真正想要的。

答案 1 :(得分:2)

现在使用它,感谢答案:

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
  }
}

这可以改进;)

答案 2 :(得分:1)

将Haskell版本翻译成Scala肯定不会太困难。这是Haskell definition of groupBy。它使用span;我不知道Scala中是否有span的等价物,或者您是否还需要翻译Haskell definition of span

答案 3 :(得分:0)

我的版本,只是搞乱 - 不太确定。我比Scala更了解Haskell但是想学习Scala:

object GroupByTest extends App {    
  val ds = Set('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', ' ')

  def isD(d: Char) = ds contains d

  def hgroupBy[A](op: A => (A => Boolean), a: List[A]): List[List[A]] = 
    a match {
      case Nil => List.empty
      case x :: xs =>
        val t = xs span op(x)         
        (x :: t._1) :: hgroupBy(op, t._2)        
    }

  val lambda: Char => Char => Boolean = x => y => isD(x) == isD(y)

  println(hgroupBy(lambda, "this is a line with 0123344334343434343434-343 3345".toList))
}