我正在尝试列出一堆不属于特定银行的数字。
这是我的代码
类型
type NI = Int
type Age = Int
type Balance = Int
type Person = (NI, Age, Balance)
type Bank = [Person]
type Market = [Bank]
type Pop = [NI]
银行
rbs :: Bank
rbs = [ (1, 73, 1000)
, (2, 18, -50)
, (3, 60, 190)
, (4, 26, 300)
, (5, 24, 456)
, (6, 32, 7500)
, (7, 41, -46)
, (8, 59, -850)
, (9, 44, 348)
, (10, 66, -1000)
clyde :: Bank
clyde = [(1, 73, 240)
, (2, 18, -70)
, (23, 30, 800)
, (14, 16, 30)
, (5, 24, 800)
, (19, 81, 750)
, (17, 49, 946)
, (20, 59, -850)
, (29, 24, -348)
, (30, 76, -100)
sco :: Pop
sco = [1..20]
这是我的代码,用于检查NI是否不在银行
bankFree :: Pop -> Market -> Pop
bankFree [] x = []
bankFree x [] = error "No Banks selected"
bankFree x [[]] = []
bankFree (x:xs) [[],((n,a,b):ys)] = if x == n then bankFree (xs) [[],ys]
else x : bankFree xs [[],ys]
bankFree x [[],[]] = []
bankFree (x:xs) (((n,a,b):ys):zs) = if x == n then bankFree (xs) ((ys):zs)
else if x /= n then x : bankFree xs ((ys):zs)
else bankFree (xs) zs
如果我运行bankFree sco [rbs,clyde]应该显示的是[11,12,13,15,16,18,20]然而出现的是[2..20]
我不知道我做错了什么以及如何继续,所以对此事的任何帮助都将不胜感激
答案 0 :(得分:5)
同样,正如我在my answer to your earlier question中所建议的那样,你遇到这么多困难的原因是你没有把问题有效地分解成小块,而你却没有帮助自己标准实用程序用于管理列表。你试图一次咬掉一块太大的东西,这很难解决。
因此,您希望将问题分解为易于自行解决的子部分,然后将这些部分组合成解决大问题的重要解决方案:
import Data.List (any)
type Market = [Bank]
type Bank = [Person]
data Person = Person { ni :: NI, age :: Age, balance :: Balance }
deriving (Eq, Show)
bankFree :: Pop -> Market -> Pop
bankFree pop banks = filter checkBanks pop
where checkBanks n = not (any (bankHasNI n banks))
bankHasNI :: NI -> Bank -> Bool
bankHasNI n bank = any (\person -> ni person == n) bank
必读:
答案 1 :(得分:2)
将其分解为更小的问题。此外,使用高阶函数而不是手动递归来使您的算法更容易理解:
inBank :: NI -> Bank -> Bool
ni `inBank` bank = any (\(ni', _, _) -> ni' == ni) bank
inMarket :: NI -> Market -> Bool
ni `inMarket` market = any (ni `inBank`) market
bankless :: Pop -> Market -> Pop
bankless pop market = filter (not . (`inMarket` market)) pop
如果你测试一下,你会得到:
>>> bankless sco [rbs, clyde]
[11,12,13,15,16,18]
答案 2 :(得分:2)
我想这是家庭作业,所以只是为你解决问题并不好,但这里有一些提示:
bankFree
函数视为过滤器是很自然的。以下是一些人,每个的人,只有在没有银行帐户的情况下才能保留。过滤列表可以通过多种不同的方式实现,对初学者来说最简单的方法可能是使用列表理解:
bankFree :: Pop -> Market -> Pop
bankFree pop market = [p | p <- pop, not (isBankCustomer market p)]
应该被理解为:返回Pop中非银行客户的所有人员。 isBankCustomer
的定义应为:
isBankCustomer :: NI -> Market -> Bool
isBankCustomer ni market = ?
你想在这里做的是以某种方式检查ni是否存在于任何银行客户名单中。