如何在scala中将每个元素与列表中的其他元素进行深入比较(可选文件)

如何在scala中将每个元素与列表中的其他元素进行深入比较(可选文件),scala,Scala,我有代表report的case类,report有费用 case class FakeExpense(amount: Option[Double], country: Option[String], currency: Option[String]) case class FakeReport(id: Int, expenses: List[FakeExpense]) 如果报告有效与否,我想返回true/false,如果有两个开支字段完全相同,则返回true/false是无效的……使用scala

我有代表report的case类,report有费用

case class FakeExpense(amount: Option[Double], country: Option[String], currency: Option[String])
case class FakeReport(id: Int, expenses: List[FakeExpense])
如果报告有效与否,我想返回true/false,如果有两个开支字段完全相同,则返回true/false是无效的……使用scala做这样的事情的正确方法是什么

有效报告:

val report = FakeReport(1, List(FakeExpense(Some(150), Some("US"), Some("USD")),FakeExpense(Some(85), Some("DE"), Some("EUR"))))
val report = FakeReport(2, List(FakeExpense(Some(150), Some("US"), Some("USD")),FakeExpense(Some(150), Some("US"), Some("USD"))))
无效报告:

val report = FakeReport(1, List(FakeExpense(Some(150), Some("US"), Some("USD")),FakeExpense(Some(85), Some("DE"), Some("EUR"))))
val report = FakeReport(2, List(FakeExpense(Some(150), Some("US"), Some("USD")),FakeExpense(Some(150), Some("US"), Some("USD"))))
谢谢

考虑这样的方法

def isValidReport(report: FakeReport): Boolean =
  report.expenses.distinct.length == report.expenses.length
上述解决方案对列表进行了三次遍历。应用路易斯的评论,我们可以减少到两次这样的传球

def isValidReport(report: FakeReport): Boolean = {
  report.expenses.sizeIs == report.expenses.iterator.distinct.length
}
因为
distinct.length
iterator.distinct.length
中折叠为单个转换,所以我们删掉了一个过程。这是一个潜在的快速节约,我们可能不必通读整个清单

这里是一个基于具有查找和插入功能的HashSet的单过程尾部递归解决方案

def isValidReport(report: FakeReport): Boolean = {
  val set = mutable.HashSet[FakeExpense]()
  @tailrec def loop(l: List[FakeExpense]): Boolean = l match {
    case Nil => true
    case h :: t => if (set.add(h)) loop(t) else false
  }
  loop(report.expenses)
}
还要注意我们如何在第一次复制时尽早返回。

如果您需要完全相同的报告,而不考虑与epsilon的双重比较(|a-b |
fakeReport.expenses.toSet.length==fakeReport.expenses.length

它将一直工作,直到类中要与==一起使用的所有内容都正确地实现了equals方法(基本类型、大多数默认类、case类和对象都这样做)。不能正确实现这一点的是数组,可能还有某些java类,这些类被包装到AnyVal类中

我会在第一个问题上使用
迭代器
,然后使用
sizeIs
来减少迭代次数。@LuisMiguelMejíaSuárez我不知道
迭代器
是如何帮助的,但是我已经用基于
哈希集
的单程解决方案更新了问题。
迭代器
distinct
之前将将迭代次数从两次减少到一次。@LuisMiguelMejíaSuárez啊,你的意思是因为
iterator.distinct.length
变成了单个转换吗?是的,无论如何你的
HashSet
解决方案更好:p