假设我想用duplicates
在列表中打印count
。所以我有3 options
,如下所示:
def dups(dup:List[Int]) = {
//1)
println(dup.groupBy(identity).collect { case (x,ys) if ys.lengthCompare(1) > 0 => (x,ys.size) }.toSeq)
//2)
println(dup.groupBy(identity).collect { case (x, List(_, _, _*)) => x }.map(x => (x, dup.count(y => x == y))))
//3)
println(dup.distinct.map((a:Int) => (a, dup.count((b:Int) => a == b )) ).filter( (pair: (Int,Int) ) => { pair._2 > 1 } ))
}
问题:
- >对于option 2
,有没有办法命名list参数,以便它可以用来附加列表的大小,就像我在option 1
中使用ys.size一样?
- >对于option 1
,有没有办法避免最后一次调用toSeq返回List?
- > 3个选项中的哪一个是more efficient by using the least amount of loops
?
作为示例输入:列表(1,1,1,2,3,4,5,5,6,100,101,101,102) 应打印:列表((1,3),(5,2),(101,2))
根据下面的@lutzh答案,最好的方法是执行以下操作:
val list: List[(Int, Int)] = dup.groupBy(identity).collect({ case (x, ys @ List(_, _, _*)) => (x, ys.size) })(breakOut)
val list2: List[(Int, Int)] = dup.groupBy(identity).collect { case (x, ys) if ys.lengthCompare(1) > 0 => (x, ys.size) }(breakOut)
答案 0 :(得分:1)
对于选项1,有什么方法可以避免最后一次调用toSeq 返回一个List?
collect
需要CanBuildFrom
,因此,如果您将其指定为所需类型的内容,则可以使用breakOut:
import collection.breakOut
val dups: List[(Int,Int)] =
dup
.groupBy(identity)
.collect({ case (x,ys) if ys.size > 1 => (x,ys.size)} )(breakOut)
collect
将使用map
创建一个新集合(就像Builder
)。通常返回类型由原点类型确定。使用breakOut,您基本上忽略原始类型并查找结果类型的构建器。因此,当collect
创建生成的集合时,它已经创建了"权利"类型,您不必再次遍历结果进行转换。
对于选项2,有没有办法命名list参数以便它 可以用来附加列表的大小,就像我在选项1中所做的那样 使用ys.size?
是的,您可以使用@
将其绑定到变量val dups: List[(Int,Int)] =
dup
.groupBy(identity)
.collect({ case (x, ys @ List(_, _, _*)) => (x, ys.size) } )(breakOut)
3个选项中哪一个更有效?
在匹配上调用dup.count似乎效率低下,因为需要再次遍历dup,我会避免这种情况。
我的猜测是守卫(如果lengthCompare(1)> 0)比List(,,_ *)模式少几个周期,但我还没有测量。而且我不打算。
免责声明:可能存在一种完全不同(且更有效)的方式,我现在无法想到。我只回答你的具体问题。