title: scala - custom (complex?) distinct function on a list of sets of a case class
body: <p>I have a simple case class:</p>
  
  <pre><code>case class OneTwo (one: String, two: String)
  </code></pre>
  
  <p>I have a simple list of sets of this case class:</p>
  
  <pre><code>val list = List(Set(OneTwo("a", "b")), Set(OneTwo("a", "b"), OneTwo("c", "d")), Set(OneTwo("e", "f")))
  </code></pre>
  
  <p>Now I have an unusual "distinct" requirement on this list: if one set is contained in another, they are equal, and the survivor should be the smaller set. E.g. in the above <code>list</code> the "ditsinct" procedure should return <code>List(Set(OneTwo("a", "b")), Set(OneTwo("e", "f")))</code>, because <code>Set(OneTwo("a", "b"))</code> is contained within <code>Set(OneTwo("a", "b"), OneTwo("c", "f"))</code> and <code>Set(OneTwo("a", "b"))</code> is smaller in size.</p>
  
  <p>Now, the following works in the REPL and compiles, (see the "but" later):</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Gives:</p>
  
  <pre><code>List[scala.collection.immutable.Set[OneTwo]] = List(Set(OneTwo(e,f)), Set(OneTwo(a,b)))
  </code></pre>
  
  <p>BUT:
  This ordering violates the Transitivity requiremnt of an ordering, therefore at run time this would throw a <code>java.lang.IllegalArgumentException: Comparison method violates its general contract!</code> Exception.</p>
  
  <p>Very simple to see why:</p>
  
  <pre><code>scala&gt; ord.compare(Set(OneTwo("a","b")), Set(OneTwo("e", "f")))
  res56: Int = -1
  
  scala&gt; ord.compare(Set(OneTwo("e","f")), Set(OneTwo("a", "b"), OneTwo("c", "d")))
  res57: Int = -1
  
  scala&gt; ord.compare(Set(OneTwo("a","b")), Set(OneTwo("a", "b"), OneTwo("c", "d")))
  res58: Int = 0
  </code></pre>
  
  <p>Which means A &lt; B, B &lt; C yet A = C. A problem.</p>
  
  <p>Bottom-line: is there any way I could do what I want to do to my list of sets of OneTwo case class? (I don't care by the way about the final order of this list, it could also result in a Set, and it doesn't have to be similar to my strategy)</p>