在 Python 中,我可以使用 itertools.groupby
将具有相同键的连续元素分组。 :
>>> items = [(1, 2), (1, 5), (1, 3), (2, 9), (3, 7), (1, 5), (1, 4)]
>>> import itertools
>>> list(key for key,it in itertools.groupby(items, lambda tup: tup[0]))
[1, 2, 3, 1]
Scala 也有 groupBy
,但它会产生不同的结果 - 一个从键指向在具有指定键的可迭代对象中找到的所有值的映射(而不是使用相同键的连续运行):
scala> val items = List((1, 2), (1, 5), (1, 3), (2, 9), (3, 7), (1, 5), (1, 4))
items: List[(Int, Int)] = List((1,2), (1,5), (1,3), (2,9), (3,7), (1,5), (1,4))
scala> items.groupBy {case (key, value) => key}
res0: scala.collection.immutable.Map[Int,List[(Int, Int)]] = Map(2 -> List((2,9)), 1 -> List((1,2), (1,5), (1,3), (1,5), (1,4)), 3 -> List((3,7)))
实现与 Python itertools.groupby
相同的最 Eloquent 方法是什么?
最佳答案
如果你只是想扔掉连续的重复项,你可以这样做:
def unchain[A](items: Seq[A]) = if (items.isEmpty) items else {
items.head +: (items zip items.drop(1)).collect{ case (l,r) if r != l => r }
}
也就是说,只需将列表与自身移动一个位置的版本进行比较,只保留不同的项目。很容易向方法添加 (same: (a1: A, a2: A) => Boolean)
参数并使用 !same(l,r)
如果你想要相同的自定义行为(例如,只需按键即可)。
如果你想保留重复项,你可以使用 Scala 的 groupBy
来获得一个非常紧凑(但效率低下)的解决方案:
def groupSequential(items: Seq[A])(same: (a1: A, a2: A) => Boolean) = {
val ns = (items zip items.drop(1)).
scanLeft(0){ (n,cc) => if (same(cc._1, cc._2)) n+1 else n }
(ns zip items).groupBy(_._1).toSeq.sortBy(_._1).map(_._2)
}
关于scala - Groupby 类似于 Python 的 itertools.groupby,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24512600/