Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy language: how to get difference between two lists of pairs

I am trying to get a difference of 1 list of pairs from another in Groovy language. Pairs are just (x,y) coordinates and they are unique. Below is a small example for simplicity. Note that lists can have dozens of pairs.

  def l1 = [[x:1, y:1]]
  def l2 = [[x:0, y:0]]
  println l1 - l2

will get [], that is an empty list but should be this: [[x:1,y:1]]

Update:

 for(n in l2) {
   l1 = l1 - n
 }

It works, but it's a black magic and is not optimized

like image 247
Ivan Voroshilin Avatar asked Nov 30 '14 18:11

Ivan Voroshilin


1 Answers

As stated in the comments, the pairs in l1 are unique (or rather: it's ok to have unique results), then you can use l1/l2 as sets:

l1 = [[x:1, y:1]]
l2 = [[x:0, y:0]]
println l1.toSet()-l2.toSet()
//; [[x:1, y:1]]

The problem originally is the [x:0,y:0] vs [x:1,y:1] part. The reason is in public static <T> Collection<T> minus(Collection<T> self, Collection<?> removeMe). The n*n branchs is chosen and the NumberAwareComperator thinks both maps are equal:

def cmp = new org.codehaus.groovy.runtime.NumberAwareComparator()
println cmp.compare(l1[0], l2[0])
//; 0 (equal!)

Which simply boils down to:

assert [x:1, y:1].hashCode() == [x:0, y:0].hashCode()
    // 120^1 + 121^1 == 120^0 + 121^0

Edit Alternative (if you can get rid of the map)

As this does not look that good of a base for, you might be better off using a save and sound comparable class for your data. e.g.:

@groovy.transform.Immutable
class Pair {
    long x,y
}

def p00 = new Pair(0,0)
def p11 = new Pair(1,1)
def p11o = new Pair(1,1)

assert [p00]-[p11] == [p00]
assert [p11]-[p00] == [p11]
assert [p00].intersect([p11]) == []
assert [p11].intersect([p00]) == []
assert [p11].intersect([p11o]) == [p11]
assert [p11].intersect([p11o]) == [p11o]

Even turning the maps into Expandos works better.

like image 76
cfrick Avatar answered Nov 15 '22 07:11

cfrick