2011-12-12 1 views
10

Sto provando a scrivere una funzione haskell che contiene due elenchi di numeri interi e genera un elenco con elementi che sono stati presi alternativamente dai due elenchi.Haskell - elementi alternati da due elenchi

ho la funzione:

blend xs ys 

Un esempio:

blend [1,2,3] [4,5,6] 

dovrebbe restituire

[1,4,2,5,3,6] 

mia logica è quella di comprimere le due liste insieme, generando le coppie di alternate elementi, quindi in qualche modo rimuoverli dalle loro tuple.

Sta rimuovendoli dalle loro tuple che non riesco a capire come implementare.

risposta

18

Che ne dici di scambiare gli argomenti durante la ricorsione-discesa?

blend (x:xs) ys = x:(blend ys xs) 
blend _ _ = [] 

È anche possibile generalizzare questo approccio per qualsiasi numero di liste (lascio a voi) o prendere i rimanenti elementi di una lista, se l'altro è vuoto:

blend _ ys = ys 
+0

Un modo molto bello per farlo! Grazie. – Shabu

6

lo farò supponi che questo è compito. A condizione che è possibile creare la seguente lista (come ha detto lei):

[(1,4),(2,5),(3,6)] 

... si può risolvere con 2 funzioni:

  1. È necessario convertire una tupla (a, b) in una lista [a, b]. Prova a utilizzare la corrispondenza del modello! Questa funzione deve essere applicata (ovvero mappata) su tutti gli elementi della lista che hai.
  2. Si avrà un elenco di elenchi, ad esempio [[1,4],[2,5],[3,6]], quindi è necessaria una funzione per concatenare le sottoliste in un'unica grande lista.

Ci sono naturalmente altri, forse superiori, modi per risolvere questo problema, ma potrebbe essere una buona idea continuare con il tuo approccio originale.

+1

Penso che una risposta a una domanda '' [compiti] 'che continua nella direzione originale sia particolarmente utile (a meno che la direzione non fosse completamente sbagliata, che, in questo caso, non lo era). –

4

Se si desidera comprimere, generare elenchi invece di tuple:

concat $ zipWith (\x y -> [x,y]) [1,2,3] [4,5,6] 

certo divertimento inutile:

concat $ zipWith ((flip(:)).(:[])) [1,2,3] [4,5,6] 

Probabilmente il modo più semplice:

import Data.List 
concat $ transpose [[1,2,3],[4,5,6]] 
2

Una soluzione senza utilizzare concat o ricorsione esplicita:

blend l = foldr($)[] . zipWith(.) (map(:)l) . map(:) 

Possiamo fare anche fare questo libero punto-

blend' = (foldr($)[].) . (.map(:)) . zipWith(.) . map(:) 


Come funziona: prima decorare entrambe le liste con gli operatori Contro

\[1,2,3] [4,5,6] -> [1:, 2:, 3:] [4:, 5:, 6:] 

poi abbiamo zip questo insieme con la composizione funzione

-> [(1:).(4:), (2:).(5:), (3:).(6:)] 

e infine piegare l'applicazione di tutte queste composizioni dal diritto alla lista vuota

-> (1:).(4:) $ (2:).(5:) $ (3:).(6:) $ [] = 1:4:2:5:3:6:[] = [1,4,2,5,3,6] 
+0

Cosa c'è di sbagliato in questo? – leftaroundabout