Interleave Liste von Listen in Haskell

8

Ich habe mich gefragt, wie ich eine Funktion in Haskell schreiben könnte, die eine Liste von Listen in eine einzelne Liste einfügt, zum Beispiel, wenn ich eine Funktion namens

hätte

interleavelists :: [[a]] -> [a]

sollte in der Lage sein, die Elemente zu verschachteln.

Beispiel: [[1,2,3] [4,5,6] [7,8]] --> [1,4,7,2,5,8,3,6] .

Die Listen können sowohl endliche als auch unendliche sein ... Kann ich foldr verwenden?

    
user1950055 06.01.2013, 20:30
quelle

4 Antworten

24

Am schnellsten schreiben Sie transpose von Data.List .

%Vor%

transpose wählt das erste Element jeder nicht leeren Liste seines Arguments aus und fügt sie in eine Liste ein. Danach folgt transpose s der Liste von tail s der Elemente des Arguments. concat Das Auflisten der Listen von transpose führt dazu, dass die Listen wie gewünscht verschachtelt werden. Es funktioniert, wenn einige Elementlisten unendlich sind, aber wenn die Liste der Listen selbst unendlich viele Elemente enthält, kommt sie natürlich nie über die Liste von head s hinaus. Aber die Handhabung dieses Falls ist ohnehin problematisch.

Die Verwendung von foldr zum Verschachteln der Listen ist nicht trivial. Angenommen, du hättest

%Vor%

interleavelists [] sollte wahrscheinlich [] ergeben, also wäre das der zero -Wert. Und

%Vor%

scheint natürlich, also

%Vor%

Aber was, wenn das zweite Argument nicht [] ist? Dann wollen Sie die Elemente des ersten Arguments von something in unterschiedlichen Abständen in das zweite Argument einfügen. Aber in welchen Entfernungen? Wenn alle Listen dieselbe Länge haben, sind die Abstände für jede Liste konstant, dann könnten Sie die Entfernung als weiteren Parameter übergeben,

%Vor%

Das ist nicht sehr hübsch, und wenn die Listen nicht alle gleich lang sind, ergibt sich was wahrscheinlich nicht die gewünschte Ausgabe ist. Aber wenn die Listen alle die gleiche Länge haben, macht es den Job.

    
Daniel Fischer 06.01.2013, 20:49
quelle
4

Einfache rekursive Version:

%Vor%

Nun, über foldr ...

    
Chris 06.01.2013 20:51
quelle
1

wir könnten machen, was Sie wollen

%Vor%

Nach Bedarf Verschachtelung [[1,2,3] [4,5,6] [7,8]] = & gt; [1, 4, 7, 2, 5, 8, 3, 6]

    
zurgl 08.01.2013 13:03
quelle
1

Der "Standard" (oder vielleicht, berühmte) Weg, Listen zu verschachteln, war an den schönen Tagen von SICP (und später, Reasoned Scheme),

%Vor%

Es kann mit foldr ,

verwendet werden %Vor%

Dies erzeugt offensichtlich nicht das Ergebnis in der von Ihnen gewünschten Reihenfolge, aber OTOH funktioniert OK, wenn die Eingabeliste der Listen unendlich ist. Ich glaube nicht, dass es eine Möglichkeit gibt, beide Anforderungen gleichzeitig zu erfüllen, da wir nicht wissen können, ob eine Eingabeliste unendlich ist oder nicht.

Die obigen Ergebnisse sind, was die Funktion insertAtDistance von Daniels Antwort erzeugen würde, wenn sie geändert wird, um immer bei a einzufügen Entfernung von 1 anstelle von d+1 :

%Vor%

Wenn es mit d+1 definiert ist, erzeugt es "flaches" Interleaving, während foldr (++/) [] schiefes Interleaving erzeugt:

%Vor%     
Will Ness 26.01.2013 15:12
quelle

Tags und Links