Haskell: Zerlegen einer Liste in 2 bei Index k

7

Ich bin ziemlich neu in Haskell, und ich habe ein paar Probleme. Ich versuche, eine Funktion zu implementieren, die eine Liste und einen Int aufnimmt. Der int soll der Index k sein, bei dem die Liste in ein Listenpaar aufgeteilt wird. Der erste enthält die ersten k Elemente der Liste und der zweite von k + 1 bis zum letzten Element. Folgendes habe ich bisher:

%Vor%

Ich kann nicht wirklich herausfinden, wie man den Split macht. Jede Hilfe wäre willkommen.

    
papercup 22.09.2012, 01:58
quelle

5 Antworten

18

Beachten Sie zunächst, dass die zu erstellende Funktion bereits in der Standardbibliothek in Prelude enthalten ist - sie heißt splitAt . Es ist nun verwirrend, seine Definition direkt zu betrachten, da es zwei Algorithmen gibt, einen, der die rekursive Standardstruktur überhaupt nicht verwendet - splitAt n xs = (take n xs, drop n xs) - und einen, der von Hand optimiert ist und ihn hässlich macht. Ersteres macht mehr intuitiven Sinn, da Sie einfach ein Präfix und ein Suffix nehmen und sie zu einem Paar zusammenfügen. Letzteres lehrt jedoch mehr und hat diese Gesamtstruktur:

%Vor%

Die Grundidee ist, dass wenn eine Liste aus einem Kopf und einem Schwanz besteht (es hat die Form x:xs ), dann ist die Liste, die von Index k + 1 abgeht, dieselbe wie die Liste, die von geht k nach dem Entfernen des ersten Elements - drop (k + 1) (x : xs) == drop k xs . Um das Präfix zu konstruieren, entfernen Sie in ähnlicher Weise das erste Element, nehmen ein kleineres Präfix und kleben das Element wieder an - take (k + 1) (x : xs) == x : take k xs .

    
gereeter 22.09.2012 02:26
quelle
2

Was ist damit?

%Vor%

Einige Tests:

%Vor%     
jimmyt 24.09.2012 23:30
quelle
1
___ qstntxt ___

Ich bin ziemlich neu in Haskell, und ich habe ein paar Probleme. Ich versuche, eine Funktion zu implementieren, die eine Liste und einen Int aufnimmt. Der int soll der Index k sein, bei dem die Liste in ein Listenpaar aufgeteilt wird. Der erste enthält die ersten k Elemente der Liste und der zweite von k + 1 bis zum letzten Element. Folgendes habe ich bisher:

%Vor%

Ich kann nicht wirklich herausfinden, wie man den Split macht. Jede Hilfe wäre willkommen.

    
___ antwort12540172 ___

Im Grunde brauchen Sie eine Möglichkeit, einen Teil des Fortschritts weiterzuleiten, während Sie die Liste durchforsten. Ich habe eine zweite Funktion verwendet, die einen Akkumulator-Parameter annimmt; es wird von split aufgerufen und ruft sich dann rekursiv auf. Es gibt fast sicher bessere Wege.

BEARBEITEN: hat alle Längenüberprüfungen entfernt, aber ich glaube, dass die Verwendung von ++ bedeutet, dass es immer noch O (n ^ 2) ist.

%Vor%

, um das Verhalten im ursprünglichen Post oder

zu erhalten %Vor%

Um das fehlerverzeihende Verhalten der standardmäßigen Funktion splitAt zu erhalten.

    
___ answer12540191 ___

Beachten Sie zunächst, dass die zu erstellende Funktion bereits in der Standardbibliothek in %code% enthalten ist - sie heißt %code% . Es ist nun verwirrend, seine Definition direkt zu betrachten, da es zwei Algorithmen gibt, einen, der die rekursive Standardstruktur überhaupt nicht verwendet - %code% - und einen, der von Hand optimiert ist und ihn hässlich macht. Ersteres macht mehr intuitiven Sinn, da Sie einfach ein Präfix und ein Suffix nehmen und sie zu einem Paar zusammenfügen. Letzteres lehrt jedoch mehr und hat diese Gesamtstruktur:

%Vor%

Die Grundidee ist, dass wenn eine Liste aus einem Kopf und einem Schwanz besteht (es hat die Form %code% ), dann ist die Liste, die von Index k + 1 abgeht, dieselbe wie die Liste, die von geht k nach dem Entfernen des ersten Elements - %code% . Um das Präfix zu konstruieren, entfernen Sie in ähnlicher Weise das erste Element, nehmen ein kleineres Präfix und kleben das Element wieder an - %code% .

    
___ qstnhdr ___ Haskell: Zerlegen einer Liste in 2 bei Index k ___ answer12574337 ___

Was ist damit?

%Vor%

Einige Tests:

%Vor%     
___ tag123list ___ Liste kann sich beziehen auf: eine verkettete Liste (eine geordnete Menge von Knoten, die jeweils auf ihren Nachfolger verweisen) oder eine Form eines dynamischen Arrays. Um nicht für HTML-Listen verwendet zu werden, verwenden Sie stattdessen [html-lists]. ___ answer12540207 ___

Siehe %code% im Vorspiel:

%Vor%     
___ answer12563508 ___

Ein üblicher Trick, um quadratisches Verhalten beim Erstellen einer Liste loszuwerden, besteht darin, sie rückwärts aufzubauen, dann umzukehren und Mark Reeds Lösung zu modifizieren:

%Vor%

Die Fehlerprüfung in sssplit ist in Ordnung, da nicht geprüft wird (eines der früheren Muster wird übereinstimmen), es sei denn, es liegt ein tatsächlicher Fehler vor.

In der Praxis möchten Sie vielleicht einige Strenge-Annotationen zu ssplit hinzufügen, um das Stack-Wachstum zu verwalten, aber das ist eine weitere Verfeinerung.

    
___ tag123haskell ___ Haskell ist eine funktionale Programmiersprache mit starker statischer Typisierung, verzögerungsfreier Auswertung, umfangreicher Parallelitäts- und Parallelitätsunterstützung und einzigartigen Abstraktionsfunktionen. ___ tag123split ___ Verwenden Sie dieses Tag für Fragen zum Trennen eines Elements (z. B. einer Zeichenfolge) in Teile, oft durch ein Trennzeichen oder einen regulären Ausdruck. ___
Mark Reed 22.09.2012 02:21
quelle
1

Ein üblicher Trick, um quadratisches Verhalten beim Erstellen einer Liste loszuwerden, besteht darin, sie rückwärts aufzubauen, dann umzukehren und Mark Reeds Lösung zu modifizieren:

%Vor%

Die Fehlerprüfung in sssplit ist in Ordnung, da nicht geprüft wird (eines der früheren Muster wird übereinstimmen), es sei denn, es liegt ein tatsächlicher Fehler vor.

In der Praxis möchten Sie vielleicht einige Strenge-Annotationen zu ssplit hinzufügen, um das Stack-Wachstum zu verwalten, aber das ist eine weitere Verfeinerung.

    
none 24.09.2012 10:51
quelle
0

Siehe splitAt im Vorspiel:

%Vor%     
jkoshy 22.09.2012 02:29
quelle

Tags und Links