scala - 案例集列表上的自定义(复杂?)不同函数 class

scala - custom (complex?) distinct function on a list of sets of a case class

我有一个简单的案例class:

case class OneTwo (one: String, two: String)

我有一个简单的案例集列表class:

val list = List(Set(OneTwo("a", "b")), Set(OneTwo("a", "b"), OneTwo("c", "d")), Set(OneTwo("e", "f")))

现在我对这个列表有一个不寻常的 "distinct" 要求:如果一个集合包含在另一个集合中,则它们是相等的,幸存者应该是较小的集合。例如。在上面的 list 中,"ditsinct" 过程应该 return List(Set(OneTwo("a", "b")), Set(OneTwo("e", "f"))),因为 Set(OneTwo("a", "b")) 包含在 Set(OneTwo("a", "b"), OneTwo("c", "f")) 中,而 Set(OneTwo("a", "b")) 更小尺寸。

现在,下面的代码在 REPL 中运行并编译,(见后面的 "but"):

def ord: Ordering[Set[OneTwo]] = new Ordering[Set[OneTwo]]() {
  def compare(set1: Set[OneTwo], set2: Set[OneTwo]): Int = {
    if (set1.equals(set2) || set1.subsetOf(set2) || set2.subsetOf(set1)) 0 else if (set1.size != set2.size) set1.size compare set2.size else
      set1.hashCode compare set2.hashCode
  }
}

val listSorted = list.sorted(ord).reverse

val listDistinct =  collection.immutable.SortedSet(listSorted: _*)(ord).toList

listDistinct

给出:

List[scala.collection.immutable.Set[OneTwo]] = List(Set(OneTwo(e,f)), Set(OneTwo(a,b)))

但是: 此排序违反了排序的传递性要求,因此在 运行 时会抛出 java.lang.IllegalArgumentException: Comparison method violates its general contract! 异常。

原因很简单:

scala> ord.compare(Set(OneTwo("a","b")), Set(OneTwo("e", "f")))
res56: Int = -1

scala> ord.compare(Set(OneTwo("e","f")), Set(OneTwo("a", "b"), OneTwo("c", "d")))
res57: Int = -1

scala> ord.compare(Set(OneTwo("a","b")), Set(OneTwo("a", "b"), OneTwo("c", "d")))
res58: Int = 0

这意味着A < B,B < C但A = C。一个问题。

底线:有什么方法可以对我的 OneTwo 案例组列表做我想做的事 class? (顺便说一句,我不关心这个列表的最终顺序,它也可能导致一个集合,而且它不必与我的策略相似)

这是一个简单的解决方案,我相信还有更优雅的方法:

list.sortBy(_.size).foldLeft(Set.empty[Set[OneTwo]])((res, set) => {
  if (res.exists(_.subsetOf(set))) res else res + set 
}).toList

按大小排序很重要,因为较小的集合会以这种方式显示在前面。之后,只需折叠列表,只添加一个满足您的约束的元素。请注意,我们在 Set 中累积结果,而不是在 List 中,因为它使约束检查更简单、更有效。