non riesce a capire come unire due liste nel seguente modo in Haskell:Unire due liste in Haskell
INPUT: [1,2,3,4,5] [11,12,13,14]
OUTPUT: [1,11,2,12,3,13,4,14,5]
non riesce a capire come unire due liste nel seguente modo in Haskell:Unire due liste in Haskell
INPUT: [1,2,3,4,5] [11,12,13,14]
OUTPUT: [1,11,2,12,3,13,4,14,5]
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
Sono nuovo alla programmazione funzionale, e il codice mi fa meravigliare questo: l'ottimizzazione chiamata coda si applica in quel anche la forma della ricorsione? –
No, non è così. La coda è chiamata (:) e non ha bisogno di ottimizzazione. – Ingo
C'è una versione più laziale di questo in [un'altra risposta] (http://stackoverflow.com/a/3987188/2157640). È pigro nel secondo parametro. – Palec
EDIT: Date un'occhiata a risposta e commenti di Ed'ka !
Altra possibilità:
merge xs ys = concatMap (\(x,y) -> [x,y]) (zip xs ys)
O, se vi piace applicativo:
merge xs ys = concat $ getZipList $ (\x y -> [x,y]) <$> ZipList xs <*> ZipList ys
Sì, a cattivo, che funziona solo su elenchi di lunghezza uguale. – bogatyrjov
Allora perché pensi così semplice (. Concat trasposizione) "non è abbastanza carina"? Presumo che hai provato qualcosa di simile:
merge :: [[a]] -> [a]
merge = concat . transpose
merge2 :: [a] -> [a] -> [a]
merge2 l r = merge [l,r]
questo modo si può evitare la ricorsione esplicita (vs la prima risposta) e ancora è più semplice rispetto alla seconda risposta. Quindi quali sono gli svantaggi?
Ah, ho dimenticato la trasposizione e ho perso il commento. Molto bello, +1 (ma non direi necessariamente che è molto più semplice della mia prima soluzione.) – danlei
Accetto. La tua soluzione è probabilmente ancora più semplice. Il vero problema però è che non è corretto al 100%: per gli elenchi di lunghezze diverse (come nell'input del campione dalla domanda) non funziona come previsto (tailing '5' manca). –
Buona cattura! Ho trascurato il 5 nell'output di esempio. Aggiornerò la mia risposta con un puntatore alla tua risposta e ai tuoi commenti. Grazie! – danlei
vi voglio proporre una versione più pigri di unione:
merge [] ys = ys
merge (x:xs) ys = x:merge ys xs
Per un caso di esempio, l'utilizzo è possibile controllare una recente domanda SO su lazy generation of combinations.
La versione nella risposta accettata è inutilmente severa nel secondo argomento ed è ciò che è migliorato qui.
Bene, questo mette tutti gli elementi di ys alla fine, quindi non funziona. Ma penso che volevi invertire l'ordine delle prime due equazioni nella soluzione di andri. – Yitz
No, fa la stessa cosa - si alterna tra ciascuna lista. Si noti che 'xs' e' ys' sono scambiati nella chiamata ricorsiva. –
È un'ottima soluzione! Vorrei poter pensare a qualcosa del genere io stesso – bogatyrjov
-- ++
pp [] [] = []
pp [] (h:t) = h:pp [] t
pp (h:t) [] = h:pp t []
pp (h:t) (a:b) = h : pp t (a:b)
Questa soluzione non è corretta. La riga finale dovrebbe essere 'pp (h: t) (a: b) = h: a: pp t b'. – bisserlis
Sicuramente un caso per un unfold:
interleave :: [a] -> [a] -> [a]
interleave = curry $ unfoldr g
where
g ([], []) = Nothing
g ([], (y:ys)) = Just (y, (ys, []))
g (x:xs, ys) = Just (x, (ys, xs))
Il tuo codice originale non ha funzionato; 'interleave [] [1,2,3]' darebbe '[]'. Penso che dovrebbe funzionare ora. – dfeuer
un altro caso per il tuo ['unfoldr''] (http://stackoverflow.com/q/24519530/849891) apomorfismo! (quindi sarà equivalente a [questa risposta] (http://stackoverflow.com/a/3987188/849891) sopra). –
@dfeuer (il commento sopra) –
Di solito si impara di più se si spiega che cosa si è tentato e perché non ha funzionato, che la gente modo può fare un po 'di riempimento-in-the- lacune invece di darti una porzione di codice. –
Correlati: [Elenco interleave di elenchi in Haskell] (http://stackoverflow.com/q/14186433/2157640) – Palec