2011-12-29 68 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