过滤一个自定义类型(元组)的列表?

3

我该如何通过元组中的第三个项目来过滤这种类型的列表:

type Car = (String, [String], Int [String])

我看到了 sndfst 方法,但我不认为这会起作用,也不确定如何进行映射而不使用 '_' 通配符。


我认为你的代码在语法上不正确。这里的“Int”不对! - phynfo
Int 后面缺少逗号。 - hammar
这听起来像是对https://dev59.com/f1bUa4cB1Zd3GeqPDfnt的重新概括,其中已经介绍了记录语法和`intercalate`。 - pat
3个回答

11

对于超过两个元素的元组,没有像fstsnd这样的预定义函数。正如你所说,您可以使用模式匹配和通配符_来完成工作。

 cars = [ ("Foo", ["x", "y"], 2009, ["ab", "cd"]
        , ("Bar", ["z"],      1997, [])
        ]

 newCars = filter condition cars
     where condition (_, _, n, _) = n > 2005

然而,这通常是一个提示,表明您应该从使用元组改为使用记录类型。

 data Car = Car { model :: String
                , foo   :: [String]
                , year  :: Int
                , bar   :: [String] 
                }

 cars = [ Car "Foo" ["x", "y"] 2009 ["ab", "cd"]
        , Car "Bar" ["z"]      1997 []
        ]

现在,您可以像在元组上使用fstsnd一样使用modelfooyearbar

 newCars = filter ((> 2005) . year) cars

这看起来很棒,使用这种方法,我如何在此类型的列表项上使用init?例如:last foo这给了我一个类型错误:Car -> [String]与类型不匹配:[a]?? - Ash
@Ash: last foo 不起作用,因为 last 需要一个列表,而 foo 是一个函数。如果你想要一辆车的最后一个 foo,你可以将这两个函数组合起来,如 (last . foo) car - hammar
@hammer:但是我只从汽车列表中提取了一辆汽车并输入到函数中,所以这样做可能不会正常工作:S,你明白我的意思吗? - Ash
@Ash:如果您能更具体地说明您想要做什么,那就太好了。 - hammar
抱歉,基本上我正在尝试在屏幕上打印特定年份的汽车列表。我使用last和init来帮助我格式化输出IO()的输出。我有两个函数,一个调用mapM和putStrLn对testData进行操作,另一个将1个电影输入并返回格式化后的字符串以便打印到屏幕上。我正在尝试添加筛选器,以便选择要馈入打印函数的项目。这样清楚一些了吗?抱歉,有时我很难解释清楚。 - Ash
1
@Ash:也许你应该创建一个新的问题,因为这个评论区已经有点太大了。请提供一个输入示例以及对应输出的期望结果。 - hammar

0

或者你可以直接使用Data.Tuple.Utils

MissingH也充满了其他好东西;我的几乎所有项目都在某个地方使用它。


0

这是我针对类似问题的解决方案:

  --construct a list of stock records with the number in stock less than the reorder level.

  getstock (name, stock, reorder) = stock
  getreorder (name, stock, reorder) = reorder

  check l = filter (\x ->(getstock x < getreorder x)) l

  main = print(check [("RAM",9,10),("ROM",12,10),("PROM",20,21)]); --[("RAM",9,10),("PROM",20,21)] 

关键在于理解过滤函数需要一个谓词,而不是布尔值。

因此,简单地说:

filter(getstock < getreorder)

是行不通的,

`filter (getstock < 10)

则可以。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接