Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala中实现groupBy方法的替代方法?_Scala_Language Features - Fatal编程技术网

在Scala中实现groupBy方法的替代方法?

在Scala中实现groupBy方法的替代方法?,scala,language-features,Scala,Language Features,我提出了这个groupBy的实现: object Whatever { def groupBy[T](in:Seq[T],p:T=>Boolean) : Map[Boolean,List[T]] = { var result = Map[Boolean,List[T]]() in.foreach(i => { val res = p(i) var existing = List[T]() // h

我提出了这个
groupBy
的实现:

object Whatever
{
    def groupBy[T](in:Seq[T],p:T=>Boolean) : Map[Boolean,List[T]] = {
        var result = Map[Boolean,List[T]]()
        in.foreach(i => {
            val res = p(i)
            var existing = List[T]() // how else could I declare the reference here? If I write var existing = null I get a compile-time error.
            if(result.contains(res))
                existing = result(res)
            else {
                existing = List[T]()
            }
            existing ::= i
            result += res -> existing
        })
        return result   
    }
}
但对我来说,它似乎不是很有鳞(这就是我要找的词吗?)。你能提出一些改进建议吗

编辑:在我收到关于折叠的“提示”后,我以这种方式实现了它:

def groupFold[T](in:Seq[T],p:T=>Boolean):Map[Boolean,List[T]] = {
        in.foldLeft(Map[Boolean,List[T]]()) ( (m,e) => {
           val res = p(e)
           m(res) = e :: m.getOrElse(res,Nil)
        })
}
你怎么看?

小提示:用于以函数式/不可变的方式计算结果列表。

我只需过滤两次

object Whatever {
  def groupBy[T](in: Seq[T], p: T => Boolean) : Map[Boolean,List[T]] = {
    Map( false -> in.filter(!p(_)).toList , true -> in.filter(p(_)).toList )
  }
}

如果您想按谓词(即
T=>Boolean
的函数)分组,那么您可能只想执行以下操作:

in partition p
如果您确实想用它创建地图,那么:

val (t, f) = in partition p
Map(true -> t, false -> f)

再说一次,你可能只是想锻炼一下。在这种情况下,折叠解决方案很好。

下面是一个使用
foldLeft
的示例

scala> def group[T, U](in: Iterable[T], f: T => U) = {
     |   in.foldLeft(Map.empty[U, List[T]]) {
     |     (map, t) =>
     |       val groupByVal = f(t)
     |       map.updated(groupByVal, t :: map.getOrElse(groupByVal, List.empty))
     |   }.mapValues(_.reverse)
     | }
group: [T,U](in: Iterable[T],f: (T) => U)java.lang.Object with scala.collection.DefaultMap[U,List[T]]

scala> val ls = List(1, 2, 3, 4, 5)
ls: List[Int] = List(1, 2, 3, 4, 5)

scala> println(group(ls, (_: Int) % 2))
Map(1 -> List(1, 3, 5), 0 -> List(2, 4))
Scala 2.8在标准库中提供了以下功能:

scala> println(ls.groupBy((_: Int) % 2)) // Built into Scala 2.8.
Map(1 -> List(1, 3, 5), 0 -> List(2, 4))

当值比布尔值多时,折叠实现特别有用。请注意,您可以用泛型U替换Boolean,这样折叠仍然有效@Geo您可能还想看看
splitAt
span
,它们的功能类似,但标准不同。第一个划分为
take
drop
,第二个划分为
takeWhile
dropWhile