2016-05-06 15 views
0

Ich möchte eine Funktion erstellen, die eine Liste aller möglichen Möglichkeiten zum Aufteilen einer Liste in zwei nicht leere Teile zurückgibt.Nehmen Sie eine variable Anzahl von Elementen aus der Liste

split :: [([a], [a])] 

Zum Beispiel:

> split [1,2,3,4] 

> [ ([1], [2,3,4]), ([1,2], [3,4]), ([1,2,3], [4]) ] 

Ich bin weit weg von der Lösung. Kann mir jemand helfen?

Antwort

0

Sicher, das ist einfach mit map, splitAt und flip.

Zuerst tun import Data.List

let split x = map (flip splitAt x) [1..length x-1] 

Ergebnis:

split [1,2,3,4] 
[([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4])] 

Erklärung der Flip - Wir verwenden map und flip Ergebnisse in diesem Beispiel

[splitAt 1 x, splitAt 2 x, splitAt 3 x] 

Flip einfach ermöglicht es uns, zu erzeugen, das erwartete Argument umdrehen mungen. Ansonsten haben wir eine Lambda wie so geschrieben konnte:

let split x = map (\z -> splitAt z x) [1..length x-1] 
+0

Vielen Dank! Ich habe nicht an diese schnelle Lösung gedacht! Danke noch einmal! –

+0

Sie können auch infix splitAt anstelle von 'flip splitAt x' verwenden. –

+0

@giuseppe_para du bist willkommen. – vikingsteve

8

Hier ist ein weiterer Ansatz mit inits und tails:

xs = Let [1,2,3,4]. Hinweis:

import Data.List 

inits xs -- returns: [[]  ,  [1], [1,2], [1,2,3], [1,2,3,4]] 
tails xs -- returns: [[1,2,3,4], [2,3,4], [3,4], [4] , []] 

So flitzen diese beiden Listen zusammen geben Ihnen alle Möglichkeiten, um die Liste in zwei Teile aufgeteilt:

zip (inits xs) (tails xs) 
    = [ ([], [1,2,3,4]), 
     ([1], [2,3,4]), 
     ([1,2], [3,4]) , 
     ([1,2,3,4], []) ] 

Wenn Sie nicht die ersten und letzten Paare wollen, nur entsprechend trimmen :

split xs = init $ tail $ zip (inits xs) (tails xs) 
+1

Es mag schön sein zu erwähnen, dass etwas Ähnliches mit 'Data.Sequence' überraschend zeit- und platzsparend ist, dank Louis Wassermans brillanter' inits'- und 'tails'-Implementierungen und in geringerem Maße auch wegen meines eigenen' zip'/' zipWith' Implementierung. – dfeuer

+0

@dfeuer warum ist es ** überraschend ** zeit- und platzsparend - ich dachte 'Data.Sequence' wäre eine ideale Lösung für diese Art von Problem. – epsilonhalbe

+0

@epsilonhalbe, ich bin weiterhin beeindruckt von seinen 'inits' und' tails'. – dfeuer

1

Wenn Sie diese Texte selbst nicht mit Bibliotheksfunktionen

umsetzen wollten
splits :: [a] -> [([a],[a])] 
splits [] = [] 
splits xx = splits' ([],xx) 
    where splits' :: ([a],[a]) -> [([a],[a])] 
     splits' [email protected](x,[]) = [xy] 
     splits' [email protected](x,y:yy) = let z = (x++[y],yy) 
           in xy:splits' z 
0

ein weiterer Ansatz mit Iterierte

Verwandte Themen