1

这应该很简单,我想,但我无法让它工作。我有一个带有属性名称的案例类。我想检查它们是否在其中重复名称...

employees.groupBy(_.name).mapValues(_.size).filter(_._2 == 1).toSeq.isEmpty

那行不通……应该吗?

4

3 回答 3

4

其他答案将起作用,但groupBy如果您有 10k 名员工并且前两个具有相同的名称,那么这将是一项昂贵的操作且效率低下。

1)短方法:(distinct内部构建所有值的HashSet)

val names = employees.map(_.name)
names.distinct != names

2)有效的方法:(在找到欺骗之前只遍历尽可能多的seq)

def hasDupes(employees: Seq[Employee]): Boolean = {
  val names = collection.mutable.Set.empty[String]
  employees.foreach { e => 
    if (names(e.name)) return true
    names += e.name
  }
  false
}

您可以使用尾递归方法将其编写为单行代码,但事实是,不可变集合比可变集合慢得多,因此如果我们要提高效率,这并不是什么好事。

3)现成的方法:(根本不建立一个集合,但是一旦发现两个名称相同,就会启动快速排序并退出(通过一个便宜的例外)。应该是有效的。)

class Dupe extends Throwable with util.control.NoStackTrace
val dupeOrd = new Ordering[Employee] {
  def compare(x: Employee, y: Employee) =
    if (x.name == y.name) throw new Dupe else x.name compare y.name
}
def hasDupes(employees: Seq[Employee]) =
  try { employees.sorted(dupeOrd); false } catch { case e: Dupe => true }

结果基准,方法 0 是 om-nom-nom 的方法 0 groupBy(在 1000 名员工向量上运行 1000 次的时间,以毫秒为单位,没有重复):

method             time  Early return if duplicate found
0  (groupBy)       1560  No
1  (distinct)      329   No
2a (mutable.Set)   255   Yes
2b (immutable.Set) 1414  Yes
3  (sorting)       666   Yes        //242 if employees already in name order
于 2013-10-14T21:55:01.043 回答
2

也许你想要:

case class Employee(name: String)
val bob = Employee("Bob")
val joe = Employee("Joe")

def haveDupes(emps: Seq[Employee]) =  emps.groupBy(_.name).exists {
 case (name, group) => group.size > 1
}

scala> haveDupes(Seq(bob))
res11: Boolean = false

scala> haveDupes(Seq(bob, bob))
res12: Boolean = true

scala> haveDupes(Seq(bob, joe))
res13: Boolean = false

scala> haveDupes(Seq(bob, joe, bob))
res14: Boolean = true
于 2013-10-14T15:06:32.593 回答
0

因为这里

employees.groupBy(_.name).mapValues(_.size).filter(_._2 == 1).toSeq.isEmpty

你不想要一个 == 而是一个 > 符号

employees.groupBy(_.name).mapValues(_.size).filter(_._2 > 1).toSeq.isEmpty

首先你 groupBy 它将返回一组元组(K,V),然后你映射每个元组以查看每个有多少个 mapValues(_.size) 然后你想检查是否有任何记录大小大于1。

于 2013-10-14T15:07:21.527 回答