【问题标题】:how can i append a value to a list inside a tuple in Haskell?如何将值附加到 Haskell 元组内的列表中?
【发布时间】:2020-02-02 01:33:55
【问题描述】:

例如,如果我有一个元组列表,例如 [("a1", ["a2", "a3"]), ("b1", ["b2", "b3"])] 我想添加a4 使用a1 & a4 作为更新列表的输入,以便我们得到 [("a1", ["a2", "a3", "a4"]), ("b1", ["b2", "b3"])] 作为输出,我将如何解决这个问题?我知道我们不能从字面上“更新”一个元组,我必须创建一个全新的列表

【问题讨论】:

  • 这种对结构的修改操作被Lens package很好地概括了。 this very recent book 似乎也为 Haskell 中的光学主题提供了非常丰富的信息。
  • 更新了标题:您正在尝试添加到元组内的 list 中,这意味着使用一个新元组创建一个新列表(和 n - 1 个预先存在的元组) 里面有一个新列表。

标签: list haskell tuples


【解决方案1】:

你可以使用递归来实现这个功能:

updateValueUsingKey :: Eq a => a -> b -> [(a, [b])] -> [(a, [b])]
updateValueUsingKey a b ((a',bs):abs)
    | a == a'   = (a',bs++[b]):abs                       -- update value if found
    | otherwise = (a',bs) : updateValueUsingKey a b abs  -- otherwise keep on recursing
updateValueUsingKey a b [] = []                          -- end the recursion if no more elements

【讨论】:

    【解决方案2】:

    如果你不能改变一个列表(更新现有元素)然后 fmap 它。

    如果你不能改变一个列表(收缩或扩展)然后绑定它。

    import Data.Maybe (fromJust)
    -- lookup will scan the List of Tuples for the Key
    -- Use Maybe since You dont know the Key you are looking may Exist or not
    updateValueUsingKey :: Eq a => a -> b -> [(a, [b])] -> Maybe [(a, [b])]
    updateValueUsingKey key value associatedList = 
        ((++[value]) <$> lookup key associatedList) 
        >>= (\v -> return $ fmap (\p -> if (fst p) == key then (key, v) else p) associatedList)
    
    -- If you know exactly the key exists then use fromJust to extract the Value out of Maybe
    updateValueUsingKey' :: Eq a => a -> b -> [(a, [b])] -> [(a, [b])]
    updateValueUsingKey' key value associatedList = fromJust $ updateValueUsingKey key value associatedList
    

    【讨论】:

      【解决方案3】:

      您所拥有的称为关联列表:每个元组都由一个名称和与该名称关联的值组成。如果您只想通过列表的“名称”(元组的第一个元素)查找列表,那么内置的 lookup 函数就足够了。由于您想更新列表,因此使用 Map 会更容易,它(假设所有名称都是唯一的)可以轻松地从您的列表中初始化。

      import qualified Data.Map as M
      
      type MyMap = M.Map String [String]
      
      append :: String -> String -> MyMap -> MyMap
      append k v = M.insertWith (flip (++)) k [v]
      

      insertWith 的函数参数被调用,新值作为第一个参数,现有值作为第二个参数。因此,(++) 单独会将您的新元素添加到列表中。由于您想追加新值,请使用flip (++) 来颠倒参数的顺序。

      例如:

      > data = M.fromList [("a1", ["a2", "a3"]), ("b1", ["b2", "b3"])]
      > data
      fromList [("a1",["a2","a3"]),("b1",["b2","b3"])]
      > append "a1" "a4" data
      fromList [("a1",["a2","a3","a4"]),("b1",["b2","b3"])]
      

      【讨论】:

        猜你喜欢
        • 2019-02-26
        • 1970-01-01
        • 1970-01-01
        • 2014-02-20
        • 2011-03-17
        • 2017-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多