Ad esempio, ho bisogno di una funzione:
gather :: Int -> [a] -> [[a]] gather n list = ???
dove gather 3 "Hello!" == ["Hel","ell","llo","ol!"]
gather 3 "Hello!" == ["Hel","ell","llo","ol!"]
.
Ho un’implementazione funzionante:
gather :: Int-> [a] -> [[a]] gather n list = unfoldr (\x -> if fst x + n > length (snd x) then Nothing else Just (take n (drop (fst x) (snd x)), (fst x + 1, snd x))) (0, list)
ma mi chiedo se c’è qualcosa già incorporato nella lingua per questo? Ho scansionato DataList ma non ho visto nulla.
Potresti usare le tails
:
gather nl = filter ((== n) . length) $ map (take n) $ tails l
o usando takeWhile
anziché filter
:
gather nl = takeWhile ((== n) . length) $ map (take n) $ tails l
MODIFICA: puoi rimuovere il passaggio del filtro facendo cadere gli ultimi n
elementi della lista restituita dalle tails
come suggerito nei commenti:
gather n = map (take n) . dropLast n . tails where dropLast n xs = zipWith const xs (drop n xs)
La caduta delle code può essere organizzata per automagicamente, grazie alle proprietà di zipping ,
import Data.List (tails) g :: Int -> [a] -> [[a]] gn = foldr (zipWith (:)) (repeat []) . take n . tails
oppure una semplice transpose . take n . tails
transpose . take n . tails
transpose . take n . tails
sarebbero sufficienti. test:
Dati prelettura.Lista> g 3 [1..10]
[[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [ 7,8,9], [8,9,10]]
Prelude Data.List> transpose. prendere 3. croce $ [1..10]
[[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [ 7,8,9], [8,9,10], [9,10], [10]]