【问题标题】:Searching through list of tuples搜索元组列表
【发布时间】:2016-11-13 19:53:04
【问题描述】:

我正在尝试编写一个接受字符串和元组对列表的函数。我想搜索元组列表,如果元组中的第一个值与输入字符串匹配,我想返回该对中的第二个值。我相信它的功能类似于lookup 功能,但我不确定如何实现它。到目前为止,这是我的想法:

search :: a -> [(a,b)] -> Maybe b
search a (x:xs) = if a == first value in x, return second value in x
-- If a is not in the list of tuples, return "Nothing"

这方面的一个例子是:

search "x" ([("x", 3), ("z", 5)]) = 3
search "x" ([("y", 3), ("z", 5)]) = Nothing

【问题讨论】:

  • 什么是S?这与lookup 有何不同完全
  • 我删除了那个 S,抱歉,它来自一个错误尝试的代码。因为查找返回“Just x”而不是“x”。
  • 是的,但是如果返回类型是Maybe b,那么你只能返回Just xx 本身的类型错误(b,而不是 Maybe b)。
  • 啊好吧我明白了!谢谢!

标签: haskell


【解决方案1】:

find 可以检索满足任意条件的第一个元素,因此您可以围绕它构建函数:

-- 'fmap snd' acts on the 'Maybe (a, b)' that 'find' gives back.
search :: Eq a => a -> [(a,b)] -> Maybe b
search a = fmap snd . find ((== a) . fst)

请注意,这与lookup 完全相同。此外,正如 leftaroundabout 所指出的,3(与Just 3 相对)不是具有Maybe b 结果类型的函数的可能结果。当您实际需要使用结果时,可以消除 Maybe 包装,例如使用 maybe 函数:

GHCi> :t maybe
maybe :: b -> (a -> b) -> Maybe a -> b
GHCi> (maybe "No x" (("x ~> " ++) . show) . search "x") ([("x", 3), ("z", 5)])
"x ~> 3"
GHCi> (maybe "No x" (("x ~> " ++) . show) . search "x") ([("y", 3), ("z", 5)])
"No x"

【讨论】:

    【解决方案2】:

    在基本情况下,如果列表为空,则返回Nothing。然后,如果头部元组的第一个元素a等于元素x,则返回第二个元素Just b。否则,它会递归地在尾部搜索。

    search :: (Eq a) => a -> [(a,b)] -> Maybe b
    search _ [] = Nothing
    search x ((a,b):xs) = if x == a then Just b else search x xs
    

    你可以在没有Maybe的情况下实现一个不安全的版本:

    search :: (Eq a) => a -> [(a,b)] -> b
    search _ [] = error "element not found"
    search x ((a,b):xs) = if x == a then b else search x xs
    

    其他选项是搜索列表而不是第一次出现,然后,空列表[] 相当于Nothing

    search :: (Eq a) => a -> [(a,b)] -> [b]
    search x = map snd . filter ((==x).fst)
    

    【讨论】:

    • 我认为 OP 想要帮助理解为什么她的代码不起作用,而不是解决方案。如果是后者,她自己可以查到lookup的定义。
    • 不,我确实想知道如何使这段代码工作。我想写一个叫做“搜索”的函数,而不仅仅是使用查找函数。我只知道它的功能类似于查找功能
    • Haskell 有一些基本的不安全函数(如head)。如果 OP 想要删除 Just 上下文,这是最简单的方法。
    • “Haskell 有一些基本的不安全函数”——这并不是创建更多它们的好主意。特别是,headtail 应该完全避免,尤其是初学者——使用它们几乎总是一个坏主意。
    • 取决于函数的使用上下文。也许 OP 确定密钥在列表中。否则,当然,安全版本会更好。
    【解决方案3】:

    只需使用结合 lambda 的简单映射:

    searchMe :: (Eq a) => a -> [(a, b)] -> [Maybe b]
    searchMe a li = map (\(x, y) -> if a == x then Just y else Nothing ) li
    

    按原样操作您的函数将无法正常工作,因为您将列表参数定义为 (x : xs),这无法让您将操作应用于元组的元素。

    【讨论】:

    • (1) (Eq a) => a -> [(a, b)] -> [Maybe b] 可以正常工作——在您的实现中,只有 x 需要具有相同类型的 a。 (2) 这给出了Maybe a 的列表,而 OP 只想要列表中的第一个 Just-value。你需要类似listToMaybe . catMaybes(两者都在Data.Maybe)来执行这最后一步。
    猜你喜欢
    • 2018-08-05
    • 2015-06-08
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    • 2014-05-01
    • 2017-11-23
    • 2021-12-12
    • 1970-01-01
    相关资源
    最近更新 更多