【问题标题】:Haskell replace element in listHaskell替换列表中的元素
【发布时间】:2012-04-12 23:40:05
【问题描述】:

haskell 中是否有任何内置函数可以替换给定索引处的元素?

例子:

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

应该给:

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

我知道我可以制作自己的函数,但它似乎应该是内置的。

【问题讨论】:

    标签: haskell built-in


    【解决方案1】:

    如果您需要更新特定索引处的元素,列表并不是最有效的数据结构。您可能需要考虑改用 Data.Sequence 中的 Seq,在这种情况下,您要查找的函数是 update :: Int -> a -> Seq a -> Seq a

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

    【讨论】:

    • 这似乎正是我所需要的。谢谢!
    • 我已经做到了。现在,如何将 Seq a 更改为 a ?
    • @MickaelBergeronNéron 您可以通过Data.Foldable.foldr (:) []Seq a 中获得[a]。如果您有 f :: a -> a -> a 操作,您可以使用一些初始元素(如 0)调用 Data.Foldable.foldr f,以获取组合的 a 值。
    • @MickaelBergeronNéron 我们还从Seq a 中得到[a]Data.Foldable.foldMap (:[])(或其他 Monoid,例如Data.Foldable.foldMap Sum 用于数字等)。
    【解决方案2】:

    据我所知(并且可以找到)它默认不存在。但是,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]
    【解决方案3】:

    确实存在数组,但列表实际上是单链表,替换元素的概念并不那么明显(访问给定索引处的元素可能表明您不应该使用列表,因此操作避免可能会鼓励它)。

    【讨论】:

      【解决方案4】:

      试试这个解决方案:

      import Data.List
      
      replaceAtIndex :: Int -> a -> [a] -> [a]    
      replaceAtIndex i x xs = take i xs ++ [x] ++ drop (i+1) xs
      

      它的工作原理如下:

      获取前 i 项,添加值 'x',添加其余 i+1 项

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-16
        • 1970-01-01
        • 2021-05-19
        • 1970-01-01
        • 1970-01-01
        • 2012-01-18
        • 1970-01-01
        相关资源
        最近更新 更多