2010-05-10 10 views

Antwort

5

Ignacio Lösung ist fast richtig glaube ich, erfordert aber einen Operator des Typs ('a ->' a -> ‚a) und führt nicht das erste Element.

def scan(f, state, it): 
    for x in it: 
    state = f(state, x) 
    yield state 
# test 
>>> snoc = lambda xs,x: xs+[x] 
>>> list(scan(snoc, [], 'abcd')) 
[['a'], ['a', 'b'], ['a', 'b', 'c'], ['a', 'b', 'c', 'd']] 
>>> list(scan(operator.add, 0, [1,2,3])) 
[1,3,6] 

Insbesondere die Art der Seq.scan ist

('State -> 'T -> 'State) -> 'State -> seq<'T> -> seq<'State> 

Der Standardansatz in Python ist ein scan mit der Art von der Art und Weise

('State -> 'State -> 'State) -> seq<'State> -> seq<'State> 

Dies kommt zu schreiben, dass Python spezifiziert reduce , die standardmäßig den gleichen Typ hat.

+1

+1, aber ich würde nachgeben, bevor Sie die erste Reduktion anwenden. Ich weiß nicht über F # 'scan, aber Haskell gibt den Anfangszustand als erstes Element zurück (was sehr sinnvoll ist): scanl (+) 0 [1,2,3] # [0,1,3, 6]. – tokland

0

Aggregatfunktionen würden reduce statt map verwenden.

Siehe http://docs.python.org/library/functions.html für weitere Informationen

+6

reduce() gibt nur den endgültigen Wert zurück. Nicht die Liste der Zwischenwerte. Also kann ich sum() bekommen, aber nicht cumsum() –

-3

Ich bin nicht sicher, aber geben Sie diese auf diese versuchen ein

map(function, iterable, ...)¶ 

Mehr auf docs.python

5

Nope.

def scan(op, seq): 
    it = iter(seq) 
    result = next(it) 
    for val in it: 
    result = op(result, val) 
    yield result 
+0

Sie sollten ein "yield result" vor der Schleife machen, sonst wird das erste Element fehlen. – sepp2k

+0

Ja, die MS-Dokumente waren ein bisschen vage, was 'Seq.scan <>() getan hat. –

+0

Thnx. Tatsächlich benötigt F # 's Seq.scan() einen anderen Parameter als Anfangszustand (Ergebnis). Thnx. –

2

Wenn es nur darum geht, Cumsum/Cumprod-Operationen durchzuführen, dann sollten Sie sich die super effizienten Operationen cumsum und cumprod von numpy für Arrays ansehen.