2011-01-03 4 views
12

Ich habe zwei Listen in Groovy und müssen den Inhalt von beiden summieren.Sum den Inhalt der 2 Liste in Groovy

Zum Beispiel:

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

erwartete ich dieses Ergebnis:

total = [2,2,2] 

Ich versuche, mit Operator + o .sum Verfahren zusammenzufassen, aber ich habe eine Verkettung der Listen.

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

Es ist Groovy genug groovy oder ich muss jedes Element der Listen loopen?

+1

Mögliche Wiederholung dieser Frage: http://stackoverflow.com/questions/4443557/overloading-operator-for-arrays-in-groovy – Northover

Antwort

33

Groovy List.transpose() Werke wie zip in einigen anderen Sprachen. Versuchen Sie dies:

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

das ist die schönste Antwort bisher (sorry no upvotes für heute verlassen). Was ist der Stern? –

+2

Es ist der [stride operator] (http://docs.codehaus.org/display/GROOVY/Operators?showChildren=false#Operators-SpreadOperator%28.%29), eine Abkürzung für 'collect' über der Liste. – ataylor

+0

Mit dieser erstaunlichen Antwort erinnerte ich mich an eine Frage, die ich zuvor gestellt hatte: [Clarity vs Obfuscation] (http://stackoverflow.com/questions/4433137/clarity-vs-obfuscation-writing-code) –

2

In den meisten funktionalen Programmiersprachen wird dies durch die Verwendung eines map2 (ocaml) oder zipWith (Haskell) Funktion gemacht, mit zum Beispiel:

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

ich keine Entsprechung in der groovy Dokumentation gefunden haben, aber anscheinend, können Sie leicht definieren zipWith (bei http://cs.calstatela.edu/wiki/index.php/Courses/CS_537/Summer_2008/Chapter_4._Collective_Groovy_datatypes gefunden):

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

Prototype (JavaScript-Framework) eine method zip() hat, das tut genau das, was Sie brauchen. Das hilft dir aber nicht, ich weiß. Lustig, ich hätte erwartet, dass Groovy etwas Ähnliches hat, aber ich konnte nichts in der Collection oder List Klasse finden.

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; 
} 

Und hier ist sie in Aktion:

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

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

Ausgang:

Wie auch immer, hier eine nicht allzu ziemlich Implementierung von zip() ist

[2, 2, 2]


Natürlich können Sie auch in einer weniger generische Art und Weise tun, wenn Sie genau Ihr Problem lösen wollen (und nicht eine allgemeine zip/Map-Funktion zu implementieren):

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

Ich weiß nicht, von eine integrierte Lösung, aber hier ist eine Abhilfe collect und die Java Queue ‚s poll() Methode:

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

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

Das ist original (+1) –

0

Wenn Sie die finden.* Sum() Lösung über ein bisschen verwirrend (sehr schön obwohl) lesen Sie können dies auch tun:

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

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

Natürlich ist es erlaubt, für komplexere Berechnungen als nur summiert werden.

Verwandte Themen