Sum the total balance for people between two ages

耗尽温柔 提交于 2019-12-24 10:29:11

问题


I'm trying to calculate the total balance of people/clients between two ages that have an account within a bank. I can get it to display the list of people that fall under the requirement.

These are the constructors

    type NI = Int
    type Age = Int
    type Balance = Int
    type Person = (NI, Age, Balance)
    type Bank = [Person]

This is the Bank

    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)
        , (11, 37, 20000)
        , (12, 29, -245)
        , (13, 55, 3090)
        ]

And this is my code to recursively check the bank

        equityA' :: Bank -> (Int, Int) -> Bank
        equityA' ((n,a,b):xs) (0,0) = error "No ages were selected"
        equityA' [] (x,y) = []
        equityA' ((n,a,b):xs) (f, s) = if  (f <= a) && (s >= a) then  (n,a,b) : equityA' xs (f, s) 
                                       else equityA' xs (f, s)

If I run equityA' rbs (40,50) the output will be [(7,41,-46),(9,44,348)]

What i'm struggling to do is to is print out the total balance of those people. I have some code down but am stuck at the actual calculation part.

The code for to check the total.

    equityAge :: Bank -> (Int, Int) -> Int              
    equityAge ((n,a,b):xs) (0,0) = error "No ages were selected"
    equityAge [] (x,y) = 0
    equityAge ((n,a,b):xs) (f, s) = 

I would be grateful for any help.


回答1:


It's quite simple if you use list comprehensions:

equityAge :: Bank -> (Int,Int) -> Int
equityAge _ (0,0) = error "No ages were selected"
equityAge [] (x,y) = 0
equityAge x (f,s) = sum [ b | (n,a,b) <-x, f <= a, a <= s]

Other than that you can apply Sarah's advice and use map and sum on your original function:

equityAge :: Bank -> (Int,Int) -> Int
equityAge _ (0,0) = error "No ages were selected"
equityAge [] (x,y) = 0
equityAge x (f,s) = sum (map(\(_,_,b) -> b) (equityA' x (f,s)))



回答2:


There are three main things I would recommend here: (a) use record types instead of tuples; (b) use standard utility functions to work with lists and other standard types; (c) write auxiliary functions to help keep all of you functions short and readable.

On the first recommendation:

data Person = Person { ni :: NI, age :: Age, balance :: Balance } deriving (Eq, Show)

Now you don't have to do any of that tuple pattern matching just to get a person's age; this record type declaration gets you functions age :: Person -> Age and balance :: Person -> Balance for free.

Example of the third recommendation: here is a function to calculate whether a Person is between two ages:

betweenAges :: Age -> Age -> Person -> Bool
betweenAges lo hi person = lo <= age person && age person <= hi

Now, using that auxiliary function and the standard filter function, you can get all the persons between two ages like this:

filter (betweenAges 18 27) rbs

To get the balance of a list of Persons you can just use the standard sum and map functions:

sum (map balance somePersons)

So the complete solution would be something like this:

-- Note how much easier to read this is when you use sum, map, filter 
-- and betweenAges!
equityAge :: Age -> Age -> Bank -> Balance
equityAge lo hi bank = sum (map balance (filter (betweenAges lo hi) bank))
    -- This could be its own top-level function if you're going to reuse it
    -- somewhere else, but here I'm putting it in a where declaration assuming
    -- that it's a throwaway.
    where betweenAges lo hi person = lo <= age person && age person <= hi

As a general rule, laboring away to figure out how to solve the issue you're tackling is not productive. The more productive strategy, I believe, is the following: (a) learn to solve your problems in terms of the functions in the basic libraries like Prelude, Data.List and Data.Maybe; (b) learn how to write those utility functions on your own. Why this way? Because (a) teaches you how to break problems down into small, reusable pieces, and (b) teaches you to understand what's going on from the bottom to the top in these programs.



来源:https://stackoverflow.com/questions/13333607/sum-the-total-balance-for-people-between-two-ages

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!