DrCantaloupe
DrCantaloupe

Reputation: 33

F# Creating function for comparing two lists containing lists

I'm trying to create a program that allows the user to check if a certain person will be interested in going to a certain arrangement. I have the types

    type InterestList = {
       Interest : string;
    }

    type Description = {
       Name        : string;
       Phone       : int
       BirthDate   : int
       Interests   : list<InterestList>

    }

    type Register = {
       RegID : list<Description>
    }


    type Arrangement = {
       Year : int
       ArrInterests : list<InterestList>
    }

If I then use a register containing all the people I'd like to check

  let reg = [
     ("Steven", 11111111, 1991, (["Soccer", "Flowers", "Jazz"]))
     ("Carl", 22222222, 1842, (["Animals", "Shopping", "Soccer"]))
     ("Karen", 33333333, 2005, (["Animals", "Volleyball", "Jazz"]))
  ];;

and have two arrangements

       let p1 = 
       [
         (1982, (["Soccer", "Jazz"]))
       ];;

       let p2 = 
       [
         (1998, (["Soccer"]))
         (1998, (["Jazz"]))
       ];;

A person will be interested in going to the arrangement if his age is greater than the age restraint on the arrangement (so if the person is born in 1982 and the arrangement has 1987, the criteria is fulfilled) and if the interests of the arrangement matches all or some of the interests of the person. I'd like to create a function extractInterested taking a register and an arrangement as arguments. Anyone?

EDIT:

I've tried something along the lines of

       let extractInterested f (person : Register list, arr : Arrangement   list) =
       if BirthYear > Year then
       (person
       |> List.map (fun x -> (x, List.tryFind (f x) arr))
       |> List.iter (function (x, None) -> printfn "%A is not interested in     going to the arrangement" x
                     | (x, Some y) -> printfn "%A is interested in going to the arrangement" x)
                     )

This should to some extent compare the two (the register of people and the arrangement), but the

      if BirthYear > Year then

doesn't seem to work.

Upvotes: 3

Views: 502

Answers (1)

Vandroiy
Vandroiy

Reputation: 6223

This is getting confused comments because the question isn't very specific. I'll try to split it into more sharply defined bits.

Step 1: What could be a suitable data structure for the given problem?

Assuming that an interest is merely a string, we need types for person, register, and arrangement. It'll be similar to the types in the question, but those aren't completely clear to me, so let's modify them a bit:

type Person =
  { Name : string
    PhoneNumber : int
    BirthYear : int
    Interests : Set<string> }

type Arrangement =
  { Year : int
    CoveredInterests : Set<string> }

type Register =
  { People : Person list }

I use sets for aggregating interests, since this disallows duplicates and simplifies identification of common interests via set intersection.

Step 2: What should the algorithm to match people with arrangements look like?

The main functionality here is to determine whether a person is interested or not, so a function like isInterested could be the main bit. The extractInterested function is then just a filter that makes use of isInterested.

let isInterested arrangement person =
    let hasCommonInterest =
        Set.intersect person.Interests arrangement.CoveredInterests
        |> Set.isEmpty |> not
    hasCommonInterest && person.BirthYear < arrangement.Year

let extractInterested register arrangement =
    List.filter (isInterested arrangement) register.People

Note the use of partial application: (isInterested arrangement) is a function that answers whether a specific person is interested in this specific arrangement.

Step 3: How are instances created and used?

This is mostly just F# record and list syntax.

let steven =
  { Name = "Steven"; PhoneNumber = 11111111; BirthYear = 1991
    Interests = set ["Soccer"; "Flowers"; "Jazz"] }

let carl =
  { Name = "Carl"; PhoneNumber = 22222222; BirthYear = 1842
    Interests = set ["Animals"; "Shopping"; "Soccer"] }

let karen =
  { Name = "Karen"; PhoneNumber = 33333333; BirthYear = 2005
    Interests = set ["Animals"; "Volleyball"; "Jazz"] }

let mainRegister = { People = [steven; carl; karen] }

let arrangement1 = { Year = 1982; CoveredInterests = set ["Soccer"; "Jazz"] }

Using via extractInterested mainRegister arrangement1 will return Carl's instance, which has the common interest of Soccer and is the only person entry with a birth year before 1982.

A hint for getting useful StackOverflow answers

The broader a question is, the harder it is to answer, so it's useful to split problems up into small, specific questions. If you keep it abstract and small, you'll probably find it already answered somewhere, and for the remaining cases, people are more likely to give you detailed advice about the most problematic part.

Solving this problem might begin with questions like "What data structure should I use for a set of interests?" or "How do I create instances of a record type I created?". I'd recommend to first determine and answer such questions using documentation or search, and if you hit a roadblock, ask a specific question about the obstacle you're struggling with.

Upvotes: 4

Related Questions