2014-11-30 22 views
6

Próbuję uzyskać różnicę 1 listy par od innej w języku Groovy. Pary są po prostu współrzędnymi (x, y) i są unikalne. Poniżej znajduje się mały przykład uproszczenia. Zauważ, że listy mogą mieć dziesiątki par.Groovy język: jak uzyskać różnicę między dwiema listami par

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

dostanie [], że jest pusta lista, ale powinny być w ten sposób: [[x 1, y 1]]

Aktualizacja:

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

Działa , ale jest to czarna magia i nie jest zoptymalizowana

+0

Co masz na myśli przez różnicę? Chcesz, aby każdy x, y z l2 był odejmowany od tego samego indeksu w l1? A ty "działasz dla mnie" na przykład sprawia, że ​​rzeczy są po prostu bardziej zagmatwane, ponieważ wątpię, że robi to, co chcesz (po prostu trzyma l1) – cfrick

+0

@cfrick Różnica jak w matematyce: odejmujemy zestaw l2 z zestawu l1. Wynikiem jest = wszystko w l1, ale nie w l2. Traktuj (x, y) jako jeden element, czyli (x, y) w l1, ale nie w l2. Oto dobry przykład: http://mrhaki.blogspot.ru/2010/08/groovy-goodness-subtracting-map-entries.html –

+0

ic. jest coś dziwnego z parą [x: 0, y: 0]. działa z 'minus()', jeśli jeden z nich nie jest "fałszerstwem" – cfrick

Odpowiedz

6

Jak stwierdzono w komentarzach, pary w l1 są unikalne (lub raczej: można uzyskać unikalne wyniki), a następnie c celu wykorzystać L1/L2 zestawach:

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

Problem pierwotnie jest [x:0,y:0] vs [x:1,y:1] części. Powodem jest public static <T> Collection<T> minus(Collection<T> self, Collection<?> removeMe). N * n branchs jest wybierany i NumberAwareComperator myśli obie mapy są równe:

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

która po prostu sprowadza się do:

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

Edit alternatywna (jeśli można pozbyć mapie)

Ponieważ nie wygląda to na tak dobrą podstawę, lepiej będzie, jeśli wykorzystasz klasę zapisu i dźwięku dla swoich danych. np .:

@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] 

Nawet obracanie mapy w Expando s działa lepiej.

+0

btw, [[x: 0, y: 0]]. ToSet(). Przecięcie ([[x: 1, y: 1]]). ToSet() również nie działa i nie mam obejścia . Najprawdopodobniej będę musiał sprawdzić to 0/0 i poradzić sobie z nim osobno. –

+0

I [x: 1, y: 1] .hashCode() == [x: 0, y: 0] .hashCode() sprawia, że ​​myślę, że to błąd w Groovy. Traktują ich tak samo, dziwnie. –

+0

@vibneiro to jest kod Java. pytanie brzmi, czy skrót NumberAwareComperator jest trochę za dużo z użyciem tylko kodów hash. zasadniczo hashcode to '120^1 + 121^1 == 120^0 + 121^0'. w całym mieście dochodzi do starć. – cfrick

Powiązane problemy