使用递归从元组中删除项目

时间:2014-07-21 15:26:15

标签: haskell

import Data.Char


type Games = (String, String, Int)

test :: [Games]
test =
    [
    ("Minecraft","mojang",100),
    ("GTA V","rockstar",500),
    ("Portal","valve",200),
    ("GTA IV","rockstar",100)
    ]

deleteAllInstances :: Eq a => a -> [a] -> [a]
deleteAllInstances a (x:xs)
    | a == x    = rest
    | otherwise = x : rest
      where
        rest = deleteAllInstances a xs
deleteAllInstances _ _ = []

所以我想让deleteAllInstances删除所有匹配项。

例如,如果我执行了deleteAllInstances "rockstar",它应该返回一个元组列表[("Minecraft","mojang",100),("Portal","valve",200),],并删除所有“rockstar”实例。

所以问题是如何让deleteAllInstances删除“rockstar”和所有相关值并输出结果?

3 个答案:

答案 0 :(得分:6)

您可能应该使用filter

filter :: (a -> Bool) -> [a] -> [a]会在列表中运行,并保留谓词映射到True的元素。

在这种情况下,你需要这样的东西:

deleteAllInstances :: String -> [Games] -> [Games] deleteAllInstances string games = filter (\(_,s,_) -> (s /= string)) games

这里没有真正需要围绕filter构建另一个函数,而且直接使用filter代码可能更具可读性。

你不是直接在这里使用递归,而是由filter抽象,它本身就是一个递归函数。递归的许多常见用法都包含在filtermapfold函数的组合中。

答案 1 :(得分:1)

这似乎是家庭作业,所以我会给你一些提示,而不是一个完整的解决方案。您的deleteAllInstances函数,因为它当前已编码,要求您传递整个三元组以匹配,而不是其中的字符串。如果您希望函数根据三元组第二位的字符串进行匹配和过滤,则可以在为函数定义参数匹配时将列表解构为三元组的级别(您可以阅读更多内容)关于参数匹配和类型解构这里:http://learnyouahaskell.com/syntax-in-functions)。

但是这可以通过使用地图和过滤器在Haskell中简单地实现,因此显式递归不是解决此问题的最惯用方法。

答案 2 :(得分:1)

以下是如何修改程序以执行您所描述的操作:

type Games = (String, String, Int)

test :: [Games]
test =
    [
    ("Minecraft","mojang",100),
    ("GTA V","rockstar",500),
    ("Portal","valve",200),
    ("GTA IV","rockstar",100)
    ]

deleteAllInstances :: String -> [Games] -> [Games]
deleteAllInstances a (x:xs)
    | a == x2   = rest
    | otherwise = x : rest
      where
        (x1,x2,x3) = x
        rest = deleteAllInstances a xs
deleteAllInstances _ _ = []

输出:

*Main> deleteAllInstances "rockstar" test
[("Minecraft","mojang",100),("Portal","valve",200)]