2010-06-18 20 views

risposta

13
cnv :: [String] -> [(String, Integer)] 
cnv [] = [] 
cnv (k:v:t) = (k, read v) : cnv t 

Se si desidera gestire dispari lunghezza sufficiente aggiungere cnv [x] = variante prima ultimo

+1

Puoi spiegare questa riga di codice cnv (k: v: t) = (k, leggi v): cnv t? AFAIK, il k v t è un parametro dalla lista k è la testa e v è la coda e cnv t è l'elemento successivo come k. La mia comprensione è corretta perché previosuly ho una funzione come questa. convertito :: [String] -> \t [(String, Integer)] convertito [] = [] convert (x: y: xs) = (x, y) convertire xs e perché quando aggiungo: xs non sta funzionando? Il k v t rappresenta un singolo elemento nella lista o nella lista intera? – peterwkc

+3

Non proprio: in 'k: v: t',' k' è la testa e 'v: t' è la coda. Quindi, 'k: v: t' mette i primi due elementi della lista in' k' e 'v' e la coda rimanente in' t'. Il tuo codice ha due problemi ovvi: (a) '(x, y)' ha tipo '(String, String)', non '(String, Integer)'; e (b) non ci sono due punti prima di 'convertire xs'. (Non puoi semplicemente fare ': xs', perché hai bisogno di' [(String, Integer)] 'ma' xs' ha tipo '[String]'.) Inoltre, un suggerimento per la formattazione: linee di indent con quattro spazi vuoti per ottieni blocchi di codice (o seleziona il tuo codice e fai clic sul pulsante "101010") e frammenti di codice surround con apici inversi (\ '... codice ... \'). –

+0

(x: xs) Ciò significa che x è la testa e l'elemento rimanente è la coda per xs. Grazie per la spiegazione. – peterwkc

8

ony's solution è un po 'più breve, ma qui è una versione non ricorsiva utilizzando splitEvery dal molto utile split library:

cnv = map (\[name, amount] -> (name, read amount :: Int)) . splitEvery 2 

I passaggi qui sono in qualche modo più chiari (almeno per me) rispetto alla versione ricorsiva.

+2

Questo è decisamente più naturale. La libreria divisa non ha abbastanza amore. È un peccato, poiché è incredibilmente utile. –

+0

Ora che 'splitEvery' sembra essere deprecato ora; usa invece ['chunksOf'] (https://hackage.haskell.org/package/split-0.2.2/docs/Data-List-Split.html#v:chunksOf). – sevko

3

Esattamente per un compito come questo trovo conveniente avere una funzione stride di prendere ogni elemento n-esimo dalla lista:

stride _ [] = [] 
stride n (x:xs) = x : stride n (drop (n-1) xs) 

Può essere utilizzato per convertire un elenco di coppie:

toPairs xs = zip (stride 2 xs) (stride 2 (drop 1 xs)) 

Un esempio (si noti che l'ultimo elemento può essere buttato via se non ha coppia):

ghci> stride 2 [1..5] 
[1,3,5] 
ghci> toPairs [1..7] 
[(1,2),(3,4),(5,6)] 

può essere ancora facilmente esteso a triplette o tuple più lunghi:

toTriplets xs = zip3 as bs cs 
    where as = stride 3 xs 
     bs = stride 3 $ drop 1 xs 
     cs = stride 3 $ drop 2 xs 

Per eseguire la conversione da String per intero nel tuo esempio, è possibile mappare read funzione rispetto al secondo passo:

let lst = ["peter","1000","michell","2000","kelly","3000"] in 
zip (stride 2 lst) (map read . stride 2 . drop 1 $ lst) :: [(String,Int)] 

che dà:

[("peter",1000),("michell",2000),("kelly",3000)]