【问题标题】:replace tuple in list of tuples - Haskell替换元组列表中的元组 - Haskell
【发布时间】:2012-05-06 21:23:03
【问题描述】:

大家好,我希望能够替换元组列表中的元组。这是我的想法:

let lst = [("john",3), ("greg",3), ("tom",2), ("rob",7), ("jason",4), ("tev",7)]

我希望能够从列表中删除任何元组,例如 ("rob",7),然后用新元组 ("ain",3) 替换它。 最后,我的最终列表将如下所示:

lst = [("john",3), ("greg",3), ("tom",2), ("ain",3), ("jason",4), ("tev",7)]

提前感谢您的帮助。

【问题讨论】:

  • 一种不同的容器类型可能比这些操作的列表更合适。例如,考虑Data.SetData.Map

标签: list haskell tuples


【解决方案1】:

这是不可能的。 Haskell 是一种纯函数式语言,所以一旦变量有了值,它就会永远保持这个值。

但是,您可以轻松地从旧列表中计算出新列表

map (\ x -> if x == ("rob",7) then ("ain",3) else x) lst

【讨论】:

  • 说“它做不到”有点不诚实,因为它可以做到,只是不像你用不纯的语言那样做,它可以 可以使用类似的性能特征(例如:手指树),尽管您当然不能使用内置列表类型。
  • “无法完成”是指 Haskell 没有变量重新分配 (:=)。我不认为手指树会改变这一点。 (但是,感谢您提到它们——我实际上并不熟悉它们,它们看起来很有趣。)从某种意义上说,StateMonads 确实让 Haskell 能够更改“变量”值,但我怀疑 OP 还没有准备好那个。
【解决方案2】:
replaceTuple :: [(String, Int)] -> (String, Int) -> (String, Int) -> [(String, Int)]
replaceTuple tups old new = map check tups where
    check tup | tup == old = new
              | otherwise  = tup


main = print $ replaceTuple [("john",3), ("greg",3), ("tom",2), ("rob",7), ("jason",4), ("tev",7)] ("tev", 7) ("newperson", 9001)

这将(正如您从类型注释中看到的那样)仅适用于 (String, Int) 的列表,这就是您所拥有的。但是,您可以定义一个更通用的替换函数,其类型签名为replace :: Eq b => [b] -> b -> b -> [b]b 必须是 Eq 类型类的实例,因为我们正在比较元素,这就是“Eq b => ...”的意思。

【讨论】:

    【解决方案3】:

    这是你可以做的:

    import qualified Data.Map.Lazy as Map
    
    lst = Map.fromList [("john",3), ("greg",3), ("tom",2), ("rob",7), ("jason",4), ("tev",7)]
    
    lst2 = Map.insert "ain" 3 $ Map.delete "rob" lst
    

    如果你使用解释型Haskell,过程基本相同:

    Prelude> import qualified Data.Map.Lazy as Map
    Prelude Data.Map.Lazy> let lst = Map.fromList [("john",3), ("greg",3), ("tom",2), ("rob",7),     ("jason",4), ("tev",7)]
    Prelude Data.Map.Lazy> lst
    fromList [("greg",3),("jason",4),("john",3),("rob",7),("tev",7),("tom",2)]
    Prelude Data.Map.Lazy> let lst2 = Map.insert "ain" 3 $ Map.delete "rob" lst
    Prelude Data.Map.Lazy> lst2
    fromList [("ain",3),("greg",3),("jason",4),("john",3),("tev",7),("tom",2)]
    

    请注意,“ain”不一定与“rob”在地图中的“位置”相同。但是,地图不像列表那样有排序的概念。

    【讨论】:

      【解决方案4】:

      当您想在列表中进行编辑时,我通常发现最简单的方法是使用 spanbreaksplitAt 分解列表,进行更改,然后将其与 @987654325 粘在一起@。所以在这种情况下,我会这样做:

      case break (\ (key,val) -> key == "rob") lst of
        (_, []) -> error "key not found! :("
        (xs, _ : ys) -> xs ++ ("ain", 3) : ys
      

      请注意,如果您使用 Data.Sequence,那么有一个函数 update 可以完全按照您的意愿进行操作,而且速度更快。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-14
        • 2023-04-02
        • 2011-03-05
        相关资源
        最近更新 更多