können Sie reverse . take n . reverse
verwandeln Sie Ihre Liste als besonders stumpfe faul natürliche Zahl durch Behandlung: leere Listen sind Null, und conses succ sind. Für faule Naturals als Listen codiert, Subtraktion drop
:
type LazyNat a = [a]
lengthLazy :: [a] -> LazyNat a
lengthLazy = id
dropLazy :: LazyNat a -> [b] -> [b]
dropLazy [] xs = xs
dropLazy (_:n) (_:xs) = dropLazy n xs
dropLazy _ _ = []
-- like Prelude.subtract, this is flip (-)
subtractLazy :: Int -> LazyNat a -> LazyNat a
subtractLazy = drop
Jetzt können wir leicht die „nehmen letzte n
“ Funktion implementieren:
takeLast n xs = dropLazy (subtractLazy n (lengthLazy xs)) xs
... und Sie werden erfreut sein zu wissen, dass Nur n
Conse müssen zu jeder Zeit im Speicher sein. Insbesondere kann takeLast 1
(oder auch takeLast N
für jedes Literal N
) in konstantem Speicher ausgeführt werden. Sie können dies überprüfen, indem Sie vergleichen, was passiert, wenn Sie takeLast 5 [1..]
mit dem ausführen, was passiert, wenn Sie in ghci ausführen.
Natürlich, ich habe versucht, über sehr suggestiv Namen zu verwenden, aber in einer realen Implementierung könnte man den ganzen Unsinn über Inline:
takeLast n xs = go xs (drop n xs) where
go lastn [] = lastn
go (_:xs) (_:n) = go xs n
go _ _ = []
nicht sicher, was Sie nach. Eine Rewrite-Regel könnte es tun, wenn dies ausreichend nahe an dem ist, was Sie wollen. –
@DanielFischer: Ich bin eher an einer allgemeinen Methode interessiert, um das zu lösen. Denken Sie an das zweite Beispiel. – false
Wenn Sie das immer noch interessiert, hängt die Antwort davon ab, wie viele Verbraucher die Liste hat; Wenn "last" der einzige ist, sollte es in konstantem Raum und O (n) -Zeit laufen; aber wenn ein anderer Verbraucher einen Verweis auf diese Liste hat, wird er ganz entstehen, wenn "letzter" über ihn bis zu seiner letzten Zelle zählt. Also O (n) Raum und Zeit. Ähnlich für das 'takeLast' in Daniel Wagners Antwort. - Oder wir können die * tatsächliche Implementierung * von Listen ändern, als selbstabgleichende Bäume mit Index als Schlüssel, mit offensichtlichen Konsequenzen.Clojure verwendet sogar klügere Bäume mit hohem Verzweigungsfaktor (32?). –