Ich habe die folgende Liste (es ist eine Länge 2 Liste, aber in meiner Zuordnung habe ich eine Länge + n Liste)
%Vor% Ich versuche, ein 3-Tupel (p1 oder p2 oder p3 oder p4 aus dem folgenden Bild) nach Listenindex ( n
) und nach Unterlistenindex ( p
) zu ersetzen.
Die Funktion sollte am Ende wie folgt aussehen:
%Vor%Zum Beispiel: (ersetzen Sie p3 für (98,98,98):
%Vor%Ich habe den Code wie folgt geplant:
Greifen Sie auf die PN zu, die ich ändern möchte. Ich erreiche es mit:
%Vor%"Ersetzen" Sie das 3-Tupel. Ich brauche hier wirklich Hilfe. Ich stecke fest. der beste Code (in meinem Kopf ist es sinnvoll), den ich gemacht habe: (Denk daran: bitte sei nicht böse auf meinen Code, ich habe Haskell erst seit 5 Wochen studiert)
%Vor% Schließlich werde ich alles wieder zusammensetzen mit splitAt
.
Ist meine Herangehensweise an das Problem richtig? Ich würde wirklich etwas Hilfe bei Schritt 2 schätzen.
Ich bin auch ein bisschen neu in Haskell, aber sehen wir mal, ob wir uns keine vernünftige Methode dazu ausdenken können.
Im Grunde versuchen wir etwas in einer Liste zu ändern. Mit funktionaler Programmierung möchte ich es ein bisschen allgemein halten, also machen wir eine Funktion update
.
Das wird jetzt einen Index, eine Funktion und eine Liste nehmen und das nth
Element in der Liste durch das Ergebnis der Funktion ersetzen, die auf es angewendet wird.
In unserem größeren Problem müssen wir jedoch in einem verschachtelten Kontext aktualisieren. Glücklicherweise nimmt unsere Funktion update
eine Funktion als Argument, also können wir update
auch innerhalb dieser% aufrufen!
All fooo
muss zweimal update (einmal innerhalb des anderen Calls) und ein bisschen "Housekeeping" machen (das Ergebnis wird korrekt in das Tupel geschrieben). Die (n-1)
und (p-1)
waren, weil Sie scheinen, beginnend bei 1
zu indizieren, während Haskell bei 0
beginnt.
Schauen wir mal, ob das mit unserem Testfall funktioniert:
%Vor%Zuerst benötigen wir eine allgemeine Funktion, um ein bestimmtes Element einer Liste abzubilden, z. B .:
%Vor%Wir können diese Funktion zweimal für die äußere Liste und die inneren Listen verwenden. Es gibt eine kleine Komplikation, da die innere Liste Teil eines Tupels ist, also brauchen wir eine andere Hilfsfunktion:
%Vor%Jetzt haben wir alles, was wir brauchen, um die Ersetzungsfunktion auf unseren Anwendungsfall anzuwenden:
%Vor% Natürlich müssen wir in der inneren Liste den alten Wert nicht berücksichtigen, also können wir const :: a -> (b -> a)
verwenden, um dieses Argument zu ignorieren.
Sie haben also versucht, eine vorgefertigte Funktion zu verwenden, (!!)
. Es könnte auf ein Element in einer Liste für Sie zugreifen, hat aber seinen Platz dort vergessen und konnte daher nicht aktualisieren. Sie haben eine Lösung, die eine andere gebrauchsfertige Funktion split
verwendet, die eine Liste in zwei Teile zerlegt, und (++)
, die sie in eins wiederverleiht.
Aber um ein echtes Gefühl dafür zu bekommen, worauf ich vermutete, dass Ihre Aufgabe in erster Linie darauf abzielte, (es ist leicht, einen Funktionsnamen zu vergessen, und es ist ebenso einfach, sich selbst einen neuen zu schreiben) können Sie versuchen, die erste, (!!)
, selbst zu schreiben. Dann würden Sie sehen, dass es wirklich einfach ist, es zu ändern, damit es die Liste auch aktualisieren kann.
Um Ihre Funktion zu schreiben, betrachten Sie sie am besten als Äquivalenzgleichung:
%Vor% Wenn n
Null ist, nehmen wir einfach das Kopfelement weg. Was machen wir, wenn es nicht ist? Wir versuchen, näher zur Null zu kommen. Sie können die Lücken ausfüllen.
Hier haben wir das gefundene Element zurückgegeben. Was, wenn wir es ersetzen wollten? Ersetzen Sie es durch was? - Dies ruft einen anderen Parameter auf,
%Vor%Jetzt können Sie den Rest vervollständigen, denke ich.
Schließlich ist Haskell eine faule Sprache. Das heißt, es ruft nur die Elemente einer Liste auf, die schließlich benötigt werden. Was, wenn Sie das 7. Element ersetzen, aber nur die ersten 3 werden später gefragt? Der Code, der split
verwendet, wird tatsächlich die 7 Elemente anfordern, so dass er die ersten 3 zurückgeben kann, wenn er später danach gefragt wird.
Nun möchten Sie in Ihrem Fall verschachtelt ersetzen, und der Wert, der den alten durch ersetzen soll, ist abhängig vom alten Wert : newVal = let (a,b,ls)=oldVal in (a,b,myRepl p ls newtuple)
. In der Tat müssen Sie mit Funktionen anstelle von Werten neu schreiben (so dass% y
vorher verwendet wurde, const y
würde gehen):
und Ihr gesamter Anruf wird myUpd n xxs (\(a,b,c)->(a,b,myUpd ... (const ...) ))
.
Tags und Links haskell