2012-04-12 9 views
14

Esiste una funzione incorporata per sostituire un elemento in un determinato indice in haskell?Haskell sostituisce l'elemento nell'elenco

Esempio:

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

dovrebbe dare:

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

so che potrei fare la mia funzione, ma sembra proprio che dovrebbe essere costruito-in.

risposta

9

Esistono array effettivi, ma le liste sono elenchi concatenati e la nozione di sostituzione di un elemento non è del tutto ovvia (e l'accesso a un elemento in un determinato indice potrebbe indicare che non si dovrebbe utilizzare un elenco, quindi operazioni che potrebbero incoraggiarlo sono evitate).

11

Per quanto ne so (e può trovare) non esiste di default. Tuttavia, esiste splitAt in Data.List così:

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

Questo è O (N) però. Se ti accorgi di farlo molto, guarda un altro tipo di dati come un array.

+6

Non è 'O (n)' in generale, ma 'O (i)', dove 'I' è l'indice di divisione (perché solo il prefisso deve essere copiato). Se quell'indice è costante, l'operazione è 'O (1)'. –

+3

È sempre una buona idea includere una firma di tipo: 'replaceAtIndex :: Int -> a -> [a] -> [a]' –

29

Se è necessario aggiornare gli elementi in un indice specifico, gli elenchi non sono la migliore struttura dati per quello. Potresti prendere in considerazione l'utilizzo di Seq da Data.Sequence, nel qual caso la funzione che stai cercando è update :: Int -> a -> Seq a -> Seq a.

> import Data.Sequence 
> update 2 "foo" $ fromList ["bar", "bar", "bar"] 
fromList ["bar","bar","foo"] 
+0

Questo sembra essere esattamente ciò di cui ho bisogno. Grazie! –

+0

Ho fatto questo. Ora, come cambio il Seq a ad? –

+0

@ MickaelBergeronNéron puoi ottenere '[a]' da 'Seq a' con' Data.Foldable.foldr (:) [] '. Se hai un'operazione 'f :: a -> a -> a', puoi chiamare' Data.Foldable.foldr f' con qualche elemento iniziale (come 0), per ottenere il valore combinato 'a'. –