开发者

Sum the content of 2 list in Groovy

I have two lists in Groovy and need to sum the contents of both.

For example:

list1 = [1,1,1]
list2 = [1,1,1]

I expected this result:

total = [2,2,2]

I try to sum with + operator o .sum method, but I have a concatenation of the lists.

[1, 1, 1, 1, 1, 1]

It's Groovy enough groovy or I need to loop eac开发者_JAVA技巧h element of the lists?


Groovy's List.transpose() works like zip in some other languages. Try this:

list1 = [1,2,3]
list2 = [4,5,6]
assert [list1, list2].transpose()*.sum() == [5,7,9]


I don't know of a built-in solution, but here's a workaround using collect and the Java Queue's poll() method:

def list1 = [1, 2, 3]
def list2 = [4, 5, 6] as Queue

assert [5, 7, 9] == list1.collect { it + list2.poll() }


In most functional programming languages, this is done by using a map2 (ocaml) or zipWith (haskell) function, with for example:

let total = List.map2 (+) list1 list2;;

I didn't find any equivalent in the groovy documentation, but apparently, you can easily define zipWith (found at http://cs.calstatela.edu/wiki/index.php/Courses/CS_537/Summer_2008/Chapter_4._Collective_Groovy_datatypes):

zipWith = {f, a, b -> 
 result = []
 0.upto(Math.min(a.size(), b.size())-1){index -> result << f(a[index], b[index])}
 result}

assert zipWith({x, y -> x + y}, [1, 2, 3], [4, 5, 6, 7]) ==  [5, 7, 9]


Prototype (JavaScript framework) has a method zip() that does exactly what you need. That doesn't help you though, I know. Funny, I would have expected Groovy to have something similar, but I could not find anything in either the Collection or List class.

Anyway, here is a not-too-pretty implementation of zip():

List.metaClass.zip = { List other, Closure cl ->
    List result = [];
    Iterator left = delegate.iterator();
    Iterator right = other.iterator();
    while(left.hasNext()&& right.hasNext()){
        result.add(
            cl.call(left.next(), right.next())
        );
    }
    result;
}

And here it is in action:

def list1 = [1, 1, 1]
def list2 = [1, 1, 1]

print (list1.zip(list2) {it1, it2 -> it1 + it2})

Output:

[2, 2, 2]


Of course you can also do it in a less generic way if you want to solve exactly your problem (and not implement a generic zip/map function) :

List.metaClass.addValues = { List other ->
    List result = [];
    Iterator left = delegate.iterator();
    Iterator right = other.iterator();
    while(left.hasNext()&& right.hasNext()){
        result.add(
            left.next() + right.next()
        );
    }
    result;
}

def list1 = [1, 1, 1]
def list2 = [1, 1, 1]

print (list1.addValues(list2))
// Output again: [2, 2, 2]


If you find the .*sum() solution above a tad confusing to read (very nice though) you can also do this:

l1=[1,2,3]
l2=[4,5,6]

println([l1,l2].transpose().collect{it[0]+it[1]})

Of course it allows for more complex calculations than just summing.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜