我有两个元组列表,如下所示:[(String,Integer)]
和[(Float,Integer)]
。每个列表都有几个元组。
对于在第二个列表中有Integer
的每个Float
,我需要检查其Integer
是否与第一个列表中的Integer
匹配,如果是,返回String
- 尽管此函数需要返回String
的列表,即[String]
以及所有结果。
我已经定义了一个函数,该函数从第二个列表中返回Integer
的列表(用于比较第一个列表中的整数)。
这应该可以使用“高阶函数”来解决。我花了相当多的时间玩map
和filter
,但还没有找到解决方案!
答案 0 :(得分:6)
您有第二个列表中的Integers
列表。我们称之为ints
。
现在你需要做两件事 - 首先,过滤(String, Integer)
列表,使其只包含ints
列表中对应整数的对,其次,将此列表转换为一个列表String
。
这两个步骤分别对应filter
和map
。
首先,您需要一个过滤功能。此函数应采用(String, Integer)
对,并在整数位于ints
列表中时返回。所以它应该有一种类型:
check :: (String, Integer) -> Bool
写这个不应该太难。一旦你拥有它,你就可以通过它过滤第一个列表。
接下来,您需要一个函数将(String, Integer)
对转换为String
。这将有类型:
extract :: (String, Integer) -> String
这也应该很容易写。 (这样的标准函数实际上存在,但是如果你只是学习它是健康的,你自己想出来的。)然后你需要将这个函数映射到你之前过滤器的结果上。
我希望这能为您提供足够的提示,让您自己获得解决方案。
答案 1 :(得分:3)
在这个例子中可以看出,准确地描述问题是多么重要,不仅对其他人而且对自己最重要。
您希望第一个列表中的字符串,其关联的整数确实出现在第二个列表中。
有了这些问题,重要的是要以小步骤完成解决方案。大多数情况下,人们不能写下立即执行的功能,但这是许多初学者认为他们必须做的事情。
首先编写函数所需的类型签名:
findFirsts :: [(String, Integer)] -> [(Float, Integer)] -> [String]
现在,从问题描述中我们可以推断,我们基本上有两件事要做:
因此,我们函数的基本框架如下:
findFirsts sis fis = map ... selected
where
selected = filter isWanted sis
isWanted :: (String, Integer) -> Bool
isWanted (_,i) = ....
您需要使用fst
,elem
和snd
函数填写空格。
旁注:我个人更倾向于使用列表解析来解决这个问题,这通常会产生更好的可读性(对我而言),而不是地图和过滤器与非平凡过滤条件的组合。
答案 2 :(得分:1)
如果您有一个整数,问题的一半是获取字符串列表。有各种可能性,例如,使用filter
和map
。但是,您可以使用“折叠”结合两种操作:
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
,然后合并结果。