tst*_*ner 10 language-agnostic functional-programming scala
我有一个未排序的列表,想要知道它中的所有项目是否都是唯一的.
我天真的做法是
val l = List(1,2,3,4,3)
def isUniqueList(l: List[Int]) = (new HashSet()++l).size == l.size
基本上,我正在检查包含列表中所有元素的Set是否具有相同的大小(因为在原始列表中出现两次的项目只会在集合中出现一次),但我不确定这是否是理想的解决方案对于这个问题.
编辑:
我的基准3个最流行的解决方案,l==l.distinct
,l.size==l.distinct.size
和阿列克谢的基于HashSet的解决方案.每个函数运行1000次,包含10个项目的唯一列表,10000个项目的唯一列表以及第三个季度中出现的一个项目复制到列表中间的相同列表.在每次运行之前,每个函数都被调用1000次来预热JIT,整个基准测试在使用System.currentTimeMillis之前运行了5次.这台机器是C2D P8400(2.26 GHz),内存为3GB,java版本是OpenJDK 64位服务器VM(1.6.0.20).java args是-Xmx1536M -Xms512M
结果:
l.size==l.distinct.size (3, 5471, 2, 6492) l==l.distinct (3, 5601, 2, 6054) Alexey's HashSet (2, 1590, 3, 781)
较大对象的结果(字符串从1KB到5KB):
l.size==l.distinct.size MutableList(4, 5566, 7, 6506) l==l.distinct MutableList(4, 5926, 3, 6075) Alexey's HashSet MutableList(2, 2341, 3, 784)
使用HashSets的解决方案肯定是最快的,正如他已经指出的使用.size并没有产生重大影响.
Ale*_*nov 15
这是我能想到的最快的纯功能解决方案:
def isUniqueList(l: List[T]) = isUniqueList1(l, new HashSet[T])
@tailrec
def isUniqueList1(l: List[T], s: Set[T]) = l match {
case Nil => true
case (h :: t) => if (s(h)) false else isUniqueList1(t, s + h)
}
Run Code Online (Sandbox Code Playgroud)
这应该更快,但使用可变数据结构(基于distinct
Vasil Remeniuk给出的实现):
def isUniqueList(l: List[T]): Boolean = {
val seen = mutable.HashSet[A]()
for (x <- this) {
if (seen(x)) {
return false
}
else {
seen += x
}
}
true
}
Run Code Online (Sandbox Code Playgroud)
这是最简单的(相当于你的):
def isUniqueList(l: List[T]) = l.toSet.size == l.size
Run Code Online (Sandbox Code Playgroud)
我只想使用distinct
方法:
scala> val l = List(1,2,3,4,3)
l: List[Int] = List(1, 2, 3, 4, 3)
scala> l.distinct.size == l.size
res2: Boolean = false
Run Code Online (Sandbox Code Playgroud)
ADD:标准distinct
实现(from scala.collection.SeqLike
)使用可变HashSet来查找重复元素:
def distinct: Repr = {
val b = newBuilder
val seen = mutable.HashSet[A]()
for (x <- this) {
if (!seen(x)) {
b += x
seen += x
}
}
b.result
}
Run Code Online (Sandbox Code Playgroud)