在Haskell中映射和过滤

时间:2012-02-12 08:38:38

标签: function haskell dictionary filter

我有两个元组列表,如下所示:[(String,Integer)][(Float,Integer)]。每个列表都有几个元组。

对于在第二个列表中有Integer的每个Float,我需要检查其Integer是否与第一个列表中的Integer匹配,如果是,返回String - 尽管此函数需要返回String的列表,即[String]以及所有结果。

我已经定义了一个函数,该函数从第二个列表中返回Integer的列表(用于比较第一个列表中的整数)。

这应该可以使用“高阶函数”来解决。我花了相当多的时间玩mapfilter,但还没有找到解决方案!

3 个答案:

答案 0 :(得分:6)

您有第二个列表中的Integers列表。我们称之为ints

现在你需要做两件事 - 首先,过滤(String, Integer)列表,使其只包含ints列表中对应整数的对,其次,将此列表转换为一个列表String

这两个步骤分别对应filtermap

首先,您需要一个过滤功能。此函数应采用(String, Integer)对,并在整数位于ints列表中时返回。所以它应该有一种类型:

check :: (String, Integer) -> Bool

写这个不应该太难。一旦你拥有它,你就可以通过它过滤第一个列表。

接下来,您需要一个函数将(String, Integer)对转换为String。这将有类型:

extract :: (String, Integer) -> String

这也应该很容易写。 (这样的标准函数实际上存在,但是如果你只是学习它是健康的,你自己想出来的。)然后你需要将这个函数映射到你之前过滤器的结果上。

我希望这能为您提供足够的提示,让您自己获得解决方案。

答案 1 :(得分:3)

在这个例子中可以看出,准确地描述问题是多么重要,不仅对其他人而且对自己最重要。

您希望第一个列表中的字符串,其关联的整数确实出现在第二个列表中。

有了这些问题,重要的是要以小步骤完成解决方案。大多数情况下,人们不能写下立即执行的功能,但这是许多初学者认为他们必须做的事情。

首先编写函数所需的类型签名:

findFirsts :: [(String, Integer)] -> [(Float, Integer)] -> [String]

现在,从问题描述中我们可以推断,我们基本上有两件事要做:

  1. 将(String,Integer)列表转换为String
  2. 列表
  3. 选择我们想要的条目。
  4. 因此,我们函数的基本框架如下:

    findFirsts sis fis = map ... selected
        where
            selected = filter isWanted sis
            isWanted :: (String, Integer) -> Bool
            isWanted (_,i) = ....
    

    您需要使用fstelemsnd函数填写空格。

    旁注:我个人更倾向于使用列表解析来解决这个问题,这通常会产生更好的可读性(对我而言),而不是地图和过滤器与非平凡过滤条件的组合。

答案 2 :(得分:1)

如果您有一个整数,问题的一半是获取字符串列表。有各种可能性,例如,使用filtermap。但是,您可以使用“折叠”结合两种操作:

findAll x axs = foldr extract [] axs where
   extract (a,y) runningList | x==y = a:runningList
                             | otherwise = runningList

--usage: 
findAll 2 [("a",2),("b",3),("c",2)]
--["c","a"]

对于折叠,您有一个起始值(此处为[])以及一个将运行值连续组合到所有列表元素的操作,从左侧(foldl)开始或从右侧开始( foldr)。此操作为extract,您可以使用它来决定是否将当前元素中的字符串添加到运行列表中。

完成这一部分后,另一半是微不足道的:你需要从(Float,Integer)列表中获取整数,为所有这些整数调用findAll,然后合并结果。