【发布时间】:2012-04-12 23:40:05
【问题描述】:
haskell 中是否有任何内置函数可以替换给定索引处的元素?
例子:
replaceAtIndex(2,"foo",["bar","bar","bar"])
应该给:
["bar", "bar", "foo"]
我知道我可以制作自己的函数,但它似乎应该是内置的。
【问题讨论】:
haskell 中是否有任何内置函数可以替换给定索引处的元素?
例子:
replaceAtIndex(2,"foo",["bar","bar","bar"])
应该给:
["bar", "bar", "foo"]
我知道我可以制作自己的函数,但它似乎应该是内置的。
【问题讨论】:
如果您需要更新特定索引处的元素,列表并不是最有效的数据结构。您可能需要考虑改用 Data.Sequence 中的 Seq,在这种情况下,您要查找的函数是 update :: Int -> a -> Seq a -> Seq a。
> import Data.Sequence
> update 2 "foo" $ fromList ["bar", "bar", "bar"]
fromList ["bar","bar","foo"]
【讨论】:
Data.Foldable.foldr (:) [] 从Seq a 中获得[a]。如果您有 f :: a -> a -> a 操作,您可以使用一些初始元素(如 0)调用 Data.Foldable.foldr f,以获取组合的 a 值。
Seq a 中得到[a] 和Data.Foldable.foldMap (:[])(或其他 Monoid,例如Data.Foldable.foldMap Sum 用于数字等)。
据我所知(并且可以找到)它默认不存在。但是,Data.List 中存在splitAt 所以:
replaceAtIndex n item ls = a ++ (item:b) where (a, (_:b)) = splitAt n ls
不过,这是 O(N)。如果您发现自己经常这样做,请查看其他数据类型,例如数组。
【讨论】:
O(n)而是O(i),其中i是拆分索引(因为只需要复制前缀)。如果该索引是常量,则操作为O(1)。
replaceAtIndex :: Int -> a -> [a] -> [a]
确实存在数组,但列表实际上是单链表,替换元素的概念并不那么明显(访问给定索引处的元素可能表明您不应该使用列表,因此操作避免可能会鼓励它)。
【讨论】:
试试这个解决方案:
import Data.List
replaceAtIndex :: Int -> a -> [a] -> [a]
replaceAtIndex i x xs = take i xs ++ [x] ++ drop (i+1) xs
它的工作原理如下:
获取前 i 项,添加值 'x',添加其余 i+1 项
【讨论】: