30

How can I compare the items in two lists and create a new list with the difference in Groovy?

user304966
  • 443
  • 1
  • 4
  • 4
  • 2
    You need to say what you mean by "difference". Is the order important? Are multiple copies important? – John Mar 30 '10 at 12:12
  • 1
    Do you mean the exclusive disjunction between two lists? i.e. https://en.wikipedia.org/wiki/Exclusive_or – Nick Grealy Nov 05 '15 at 23:51

4 Answers4

61

I'd just use the arithmetic operators, I think it's much more obvious what's going on:

def a = ["foo", "bar", "baz", "baz"]
def b = ["foo", "qux"]

assert ["bar", "baz", "baz", "qux"] == ((a - b) + (b - a))
Ted Naleid
  • 26,511
  • 10
  • 70
  • 81
47

Collections intersect might help you with that even if it is a little tricky to reverse it. Maybe something like this:

def collection1 = ["test", "a"]
def collection2 = ["test", "b"]
def commons = collection1.intersect(collection2)
def difference = collection1.plus(collection2)
difference.removeAll(commons)
assert ["a", "b"] == difference
Daff
  • 43,734
  • 9
  • 106
  • 120
15

I assume the OP is asking for the exclusive disjunction between two lists.

(Note: Neither of the previous solutions handle duplicates!)

If you want to code it yourself in Groovy, do the following:

def a = ['a','b','c','c','c'] // diff is [b, c, c]
def b = ['a','d','c']         // diff is [d]

// for quick comparison
assert (a.sort() == b.sort()) == false

// to get the differences, remove the intersection from both
a.intersect(b).each{a.remove(it);b.remove(it)}
assert a == ['b','c','c']
assert b == ['d']
assert (a + b) == ['b','c','c','d']    // all diffs

One gotcha when using lists/arrays of ints. You may have problems due to the polymorphic method remove(int) vs remove(Object). See here for a (untested) solution.

Rather than reinventing the wheel, you should just use a library (e.g. commons-collections):

@Grab('commons-collections:commons-collections:3.2.1')

import static org.apache.commons.collections.CollectionUtils.*

def a = ['a','b','c','c','c'] // diff is [b, c, c]
def b = ['a','d','c']         // diff is [d]

assert disjunction(a, b) == ['b', 'c', 'c', 'd']
Nick Grealy
  • 24,216
  • 9
  • 104
  • 119
0

If it is a list of numbers, you can do this:

def before = [0, 0, 1, 0]
def after = [0, 1, 1, 0]
def difference =[]
for (def i=0; i<4; i++){
    difference<<after[i]-before[i]
}
println difference //[0, 1, 0, 0]
Mate Mrše
  • 7,997
  • 10
  • 40
  • 77