2011-01-03 12 views
12

Tengo dos listas en Groovy y necesito sumar el contenido de ambas.Sume el contenido de la lista 2 en Groovy

Por ejemplo:

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

me esperaba este resultado:

total = [2,2,2] 

trato de resumir con el método + .sum operador o, pero tengo una concatenación de las listas.

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

¿Es Groovy lo suficientemente groovy o necesito hacer un bucle en cada elemento de las listas?

+1

Posible repetición de esta pregunta: http://stackoverflow.com/questions/4443557/overloading-operator-for-arrays-in-groovy – Northover

Respuesta

33

de Groovy List.transpose() obras como zip en algunos otros idiomas. Pruebe esto:

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

esa es la mejor respuesta hasta el momento (lo siento, no hay votaciones al aire izquierda por hoy). ¿Cuál es la estrella? –

+2

Es el [operador de difusión] (http://docs.codehaus.org/display/GROOVY/Operators?showChildren=false#Operators-SpreadOperator%28.%29), abreviatura de 'collect' sobre la lista. – ataylor

+0

Con esta increíble respuesta, recordé una pregunta que hice antes: [Claridad vs Ofuscación] (http://stackoverflow.com/questions/4433137/clarity-vs-obfuscation-writing-code) –

2

En lenguajes de programación más funcionales, esto se hace mediante el uso de una función map2 (ocaml) o zipWith (Haskell), por ejemplo:

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

No se encontró ninguna equivalente en la documentación maravilloso, pero al parecer, se puede definir fácilmente zipWith (que se encuentra en 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] 
1

Prototipo (marco de JavaScript) tiene un method zip() que hace exactamente lo que necesita. Eso no te ayuda, lo sé. Es curioso, esperaba que Groovy tuviera algo similar, pero no pude encontrar nada en la clase Collection o List.

De todos modos, aquí hay una aplicación no muy bonita de 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; 
} 

Y aquí está en acción:

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

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

Salida:

[2, 2, 2]


Por supuesto, también puede hacerlo de una manera menos genérico si se quiere resolver con exactitud su problema (y no aplicar una función genérica zip/mapa):

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

no sé de una solución integrada, pero aquí es una solución utilizando collect y poll() método Java Queue 's:

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

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

Eso es original (+1) –

0

Si encuentra la.* Sum() solución anterior un poco confuso para leer (muy agradable, aunque) también se puede hacer esto:

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

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

Por supuesto que permite cálculos más complejos que simplemente sumando.

Cuestiones relacionadas