[英]Alternative way of implementing a groupBy method in Scala?
I've come up with this implementation of groupBy
: 我想出了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
}
}
but it doesn't seem very Scalish ( is that the word I'm looking for? ) to me. 但对我来说,它似乎并不是非常Scalish(我正在寻找的那个词吗?)。 Could you maybe suggest some improvements? 你能否提出一些改进建议?
EDIT: after I received the "hint" about folding, I've implemented it this way: 编辑:在我收到关于折叠的“提示”后,我已经这样实现了:
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)
})
}
What do you think? 你怎么看?
If you want to group by a predicate (ie, a function of T => Boolean
), then you probably just want to do this: 如果你想按谓词分组(即T => Boolean
的函数),那么你可能只想这样做:
in partition p
If you truly want to create a map out of it, then: 如果你真的想从中创建一个地图,那么:
val (t, f) = in partition p
Map(true -> t, false -> f)
Then again, you may just want the exercise. 然后,你可能只想要练习。 In that case, the fold solution is fine. 在这种情况下,折叠解决方案很好。
Here's an example using foldLeft
. 这是使用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 offers this in the standard library: Scala 2.8在标准库中提供:
scala> println(ls.groupBy((_: Int) % 2)) // Built into Scala 2.8.
Map(1 -> List(1, 3, 5), 0 -> List(2, 4))
I'd just filter twice. 我只是过滤两次。
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 )
}
}
小提示:使用折叠以函数/不可变的方式计算结果列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.