2011-01-25 5 views
5

Eventuali duplicati:
List comprehension for running totalPython di lista

Sto cercando di scrivere una dichiarazione concisa lista di comprensione per creare un CDF: Per esempio:

print f([0.2, 0.3,0.1,0.4]) 
[0.2,0.5,0.6,1.0] 

Una procedura standard sarebbe simile a questa (voglio scrivere una lista di comprensione per e function f()):

def f(probabilities) : 

    sum = 0 
    returnList = [] 
    for count in probabilities: 
     sum +=count 
     returnList = returnList + [sum] 
    return returnList 

Modifica: Ho trovato una funzione numpy.cumsum(). Controllerò se utilizza le list comprehensions.

+0

Qual è la domanda? – Elalfer

+0

@Elalfer - Sembra che voglia scrivere una list comprehension il cui comportamento è identico a quello della sua funzione 'f()'. –

+0

Questo è corretto. Il mio male, avrei dovuto essere più esplicito. – GeneralBecos

risposta

8

Questa operazione è così comune che molte lingue (principalmente funzionali, ma non solo) forniscono astrazioni per questo, di solito con il nome scanl (è come un reduce con risultati intermedi). Chiamiamola ireduce ("iterativo ridurre"):

def ireduce(f, state, it): 
    for x in it: 
     state = f(state, x) 
     yield state 

E ora usarlo:

import operator 

def f(probabilities): 
    return ireduce(operator.add, 0, probabilities) 

print(list(f([0.2, 0.3,0.1,0.4]))) 
# [0.2, 0.5, 0.6, 1.0] 
+0

Questa è una buona cosa da avere nella propria cassetta degli attrezzi; ma sicuramente possiamo pensare ad un nome più pitonico piuttosto che copiare quello che le altre lingue chiamano? FWIW, C++ chiama questo 'std :: partial_sum' e utilizza l'aggiunta come operazione per impostazione predefinita. –

+0

@Karl. Alcuni lo chiamano ireduce, mi piace un po '. "partial_sum" è un buon nome quando si aggiunge ma con altre operazioni sembra in qualche modo fuorviante. – tokland

8
[sum(probabilities[:i+1]) for i in range(len(probabilities))] 

Ma non farlo perché è O (n^2). Le comprensioni delle liste Python non sono state progettate per questo. Usa il codice procedurale che hai già scritto.

+0

Questa è una fantastica lista di comprensione. – user225312

1

Non è davvero bella, e non sta usando list comprehension, ma si può fare questo con il ridurre() funzione, se il valore accumulato è una tupla tiene la somma corrente e l'elenco dei risultati: mancanza di supporto per multi-linea di lambda

a = [0.2, 0.3, 0.1, 0.4] 
reduce((lambda result, val: (result[0] + val, result[1] + [result[0] + val])), a, (0, []))[1] 

di Python rende questo tipo di brutto. Usando una funzione separata sarebbe meglio:

a = [0.2, 0.3, 0.1, 0.4] 
    def accumulate(result, val): 
     return (result[0] + val, result[1] + [result[0] + val]) 

    reduce(accumulate, a, (0, []))[1]