2012-04-12 8 views
14

Gibt es eine eingebaute Funktion, um ein Element bei einem bestimmten Index in Haskell zu ersetzen?Haskell ersetze Element in der Liste

Beispiel:

replaceAtIndex(2,"foo",["bar","bar","bar"])

Sollte geben:

["bar", "bar", "foo"] 

Ich weiß, ich könnte meine eigene Funktion machen, aber es scheint nur sollte es eingebaut werden.

Antwort

9

Es gibt tatsächliche Arrays, aber Listen sind wirklich einfach verkettete Listen und die Vorstellung, ein Element zu ersetzen, ist nicht ganz so offensichtlich (und der Zugriff auf ein Element bei einem gegebenen Index kann bedeuten, dass Sie keine Liste verwenden sollten Operationen, die dies fördern könnten, werden vermieden).

11

Soweit ich weiß (und finden kann) existiert es standardmäßig nicht. Es gibt jedoch splitAt in Data.List so:

replaceAtIndex n item ls = a ++ (item:b) where (a, (_:b)) = splitAt n ls 

Dies ist O (N) though. Wenn Sie sich häufig dabei befinden, schauen Sie sich einen anderen Datentyp an, z. B. Array.

+6

Es ist nicht 'O (n)' im Allgemeinen aber 'O (i)', wo 'i' der geteilte Index ist (weil nur das Präfix kopiert werden muss). Wenn dieser Index konstant ist, lautet die Operation "O (1)". –

+3

Immer eine gute Idee, eine Typ-Signatur aufzunehmen: 'replaceAtIndex :: Int -> a -> [a] -> [a]' –

29

Wenn Sie Elemente in einem bestimmten Index aktualisieren müssen, sind Listen nicht die beste Datenstruktur dafür. Sie können stattdessen die Verwendung von Seq von Data.Sequence in Erwägung ziehen. In diesem Fall ist die gesuchte Funktion update :: Int -> a -> Seq a -> Seq a.

+0

Dies scheint genau das zu sein, was ich brauche. Vielen Dank! –

+0

Ich habe das getan. Nun, wie ändere ich die Seq a zu einem? –

+0

@ MickaelBergeronNéron können Sie mit 'Data.Foldable.foldr (:) []' '[a] 'aus' Seq a' bekommen. Wenn Sie eine 'f :: a -> a -> a'-Operation haben, können Sie' Data.Foldable.foldr f' mit einem Anfangselement (wie 0) aufrufen, um den kombinierten 'a'-Wert zu erhalten. –