2011-05-26 22 views
8

Ésta es probablemente muy simple y estoy pasando por alto algo ...Encuentra la suma de subconjuntos de una lista en Python

que tienen una larga lista de números enteros, en este caso en representación de visitantes diarios a un sitio web. Quiero una nueva lista de visitantes semanales. Entonces necesito obtener grupos de siete de la lista original, sumarlos y agregarlos a una nueva lista.

Mi solución parece bastante fuerza bruta, poco elegante:

numweeks = len(daily)/7 
weekly = [] 
for x in range(numweeks): 
    y = x*7 
    weekly.append(sum(visitors[y:y+7])) 

¿Hay una manera más eficiente, o más Pythonic de hacer esto?

+1

Esto es realmente una buena pregunta para codereview.stackexchange.com, que es sp ecológicamente para mejorar el código que funciona para hacerlo más rápido/más elegante. –

+0

Gracias ... no sabía sobre ese sitio stackexchange. Es difícil saber cuál es el apropiado para cada pregunta, especialmente dado que hay tantos en estos días. Además, este parece tener todos los ojos, así que siempre siento que el original es el mejor. :) – fitzgeraldsteele

+0

Nada de malo en este código: es sencillo y comunica bien su intención. Simplemente cambiaría los nombres de las var a algo más descriptivo que 'x' y' y', pero de lo contrario, esto es preferible a cualquier truco basado en la comprensión –

Respuesta

10
weekly = [ sum(visitors[x:x+7]) for x in range(0, len(daily), 7)] 

o ligeramente menor densidad:

weekly = [] 
for x in range(0, len(daily), 7): 
    weekly.append(sum(visitors[x:x+7])) 

alternativa, utilizando el módulo numpy.

by_week = numpy.reshape(visitors, (7, -1)) 
weekly = numpy.sum(by_week, axis = 1) 

Tenga en cuenta que esto requiere que el número de elementos de visitante sea un múltiplo de 7. También requiere que se instale numpy. Sin embargo, probablemente también sea más eficiente que los otros enfoques.

O para itertools código de bono:

def grouper(n, iterable, fillvalue=None): 
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return itertools.izip_longest(fillvalue=fillvalue, *args) 

weekly = map(sum, grouper(7, visitors, 0)) 
+0

+1 para reemplazar 'y = x * 7' con otra arg a' range() '. – John

+0

+1 por incluir el caso itertools.izip_longest, que esperaba que no tuvieras, así que podría mencionarlo. :-) –

+0

Además, para grandes conjuntos de visitantes o si los visitantes son un generador, las opciones itertools.izip_longest e itertools.imap son más eficientes, y usaría una llamada 'xrange' en lugar de' range' en la primera ejemplo. –

0
>>> daily = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] 
>>> print [sum(daily[x:x+7]) for x in range(0, len(daily), 7)] 
[28, 77, 105] 

no estoy seguro si esto es "Pythonic", pero realmente encanta este producto de una línea de pitón.

detalles morbosos: Comprehensions

0

Uso itertools.islice:

weekly = [sum(list(itertools.islice(daily, i, i+7))) 
      for i in range(0, len(daily), 7)] 

Editar:

o, con math.fsum:

weekly = [math.fsum(itertools.islice(daily, i, i+7)) 
      for i in range(0, len(daily), 7)] 
+0

El uso de islice así no será muy eficiente. Vas a iterar sobre los elementos en todos los días repetidamente de esa manera. –

Cuestiones relacionadas