2011-12-29 69 views
1

我是哈斯克尔的新手,我有一个问题(又名作业)。字符和字符串

所以,我有一个元组的列表 - 一个字符串和一个整数

xxs :: [([Char], Integer)] 

我需要知道有多少XXS字符串与给定字符开头。 让我举例说明:

foo 'A' [("Abc",12),("Axx",34),("Zab",56)] 
Output: 2 

foo 'B' [("Abc",12),("Bxx",34),("Zab",56)] 
Output: 1 

我最好的尝试至今:

foo c xxs = length (foldl (\acc (x:xs) -> if x == c then c else x) [] xxs) 

但是,当然,有一些lambda表达式里面非常错误的。

有什么建议吗? 谢谢。

+2

你有正确的预感。查看传入你的lambda的第二个参数;您定义模式的方式,Haskell需要一个列表。如果'xxs'是一个列表列表,那就没问题,但它只是一个元组列表。尝试使用像'(x,y)'这样的模式,然后查看让你感觉到的位置。希望这可以帮助! – sczizzo 2011-12-29 04:44:49

+1

@sczizzo谢谢。它真的帮助我。 – Dussel 2011-12-29 16:24:05

回答

2

有你尝试了几个问题:

  1. 您打算使用foldl构建一个更短的列表,然后把它的长度。虽然有可能,但filter函数更适合执行此任务,因为@landei建议使用

  2. foldl可用于累积长度而不构建较短的列表。看到@吴兴波的回答 - 他的回答是不正确的,但一旦你意识到length根本不需要他的方法,那么你应该很容易找到正确的解决方案。

  3. 与常识有点矛盾,用懒惰的语言foldrfoldl更快,使用的内存也更少。你应该问你的老师为什么。

4

可以使用折叠,但我会建议另一种方式,它打破三个步骤的问题:

  • 将输入列表中的第一个字母列表。您可以使用map这个
  • filter出去不等于给定Char
  • 所有元素在剩下的列表

显然,第一步是最难的length,但并不难,因为它看起来。为了做到这一点,你只需要以某种方式组合功能fsthead,或者更容易,两次映射。

你可以写这是一个简单的一行,但也许你应该用let开始:

foo c xxs = let strings = map ... 
       firstLetters = map ... 
       filteredLetters = filter ... 
      in length ... 
+0

步骤1可以合并到第2步。只需根据元组的第一部分中的字符串的第一个字母是否正确来过滤该列表。这似乎是op正在尝试的方法,通过用foldl编写自己的“过滤器”。 – 2011-12-29 16:14:35

+0

这是正确的,但您可以看到发生了什么事情时,试图一次做太多的步骤:-) – Landei 2011-12-29 17:51:04

0

我会改写富作为

foo :: Char -> [(String, Int)] -> Int 
foo c = length . filter ((==c).head.fst) 

fst获取的第一要素两元组元组。

(==c)是一个单参数函数,它将输入与c进行比较(请参阅http://www.haskell.org/tutorial/functions.html段落3.2.1以获得更好的解释)。

+0

提供作业的答案是不欢迎在SO。 – nponeccop 2011-12-29 10:47:44