Search list of tuples f# - list

Say that I have a self made dictionary made from a list of tuples
let menu = [("pizza",17);("hotdog",5);("burger", 12);("drink",3);("milkshake",4)]
I want to write a search function that takes both my dictionary and a key value as a parameter, then returns an option type with the value if key can be found in dict, and None if it can't.
I feel like this is a problem built around f# recursion, using and returning option types as well as obtaining individual values from a tuple, but I'm having a hell of a time putting them together and getting anything that comes even remotely close to accomplishing this task.
I've come up with some pseudo-code that I believe would solve the problem, but actual f# implementation is another story. In an imperative language this seems like a trivial problem, but trying to grasp functional has been really difficult.
//create function `search` accepts dictionary and search key
//match searchkey with dictionary key
//if searchkey = dictionary key, return option type w/ value
//if searchkey <> dictionary key, recurse call next dict values
//if end of dictionary, doesn't exist, return none
//Here's a *very* rough sketch of what I think should be happening.
let rec search dict key =
match dict with
//first check for an empty list, if empty return None
| [] -> None
//next check that there is a head and a tail for dict
//also check for match between first element of head and key
//if match, return hd
//still needs to return option type though, but how?
| hd :: tl when fst hd = key -> snd hd
//finally call search on the tail
| _ :: tl -> search tl key
The empty list condition and the wildcard pattern I'm fairly sure are correct, but it's the actual check and return that im stuck on. How might I go about that particular step?

Patterns can be nested inside other patterns. The tuple pattern (a, b) can be nested inside the list head/tail pattern head :: tail like this: (a, b) :: tail
This means the second pattern match can look like this (k, v) :: _ when k = key.
You need to return an option from every branch, so either a Some x or a None. The second match branch was missing a Some wrapper.
The code with both changes:
let rec search dict key =
match dict with
| [] -> None
| (k, v) :: _ when k = key -> Some v
| _ :: tl -> search tl key

They way to think about recursion, is to just get one example right. And leave the remaining list to the recursive function. And you must somehow accomplish that the "remaining" list gets smaller.
First, you deal with a list. One way to think about it is to just check one element at a time. So you extract the first element of a list, do something with it, then repeat the recursive function on the remaining list. So you could start with:
let search key lst =
match lst with
| head :: tail ->
Think of your example list, in this case. The first invocation of your example list your head would be ("pizza",17).
The next step you now need to-do is. Deconstruct the tuple into key and value and check them. You deconstruct it with
let (k, v) = head
Then you need to check if your k is equal to key. If it is equal, then you want to return the value.
if k = key
then Some v
The else branch must handle the case where your k is not the key you search. This is the recursive step. You want to repeat the checking on the remaining list items.
else search key tail
Remember at this point tail is now your menu with the first element removed. Currently you have the following code.
let rec search key lst =
match lst with
| head :: tail ->
let (k, v) = head
if k = key
then Some v
else search key tail
But this code does not handle the case when it cannot find your item. Think what would happen if the if k = key is never true! It will remove one-element at a time, then recursive on the remaining list until you end up with the empty list.
Empty list then means, you didn't find the key. To be successful you now need to add a case for the empty list. In that case your key is not in your list, and you must return "None". So you end up with:
let rec search key lst =
match lst with
| [] -> None
| head :: tail ->
let (k, v) = head
if k = key
then Some v
else search key tail

Related

Insert number into sorted list using List.fold_right

I am trying to insert a number x into a sorted list l using Ocaml's List.fold_right and return the list with the inserted element. I have figured out a way to insert it if the element is to go at the front of the list or in the middle of the list, however I cannot figure out how to code the case where the element is larger than every element in the list and thus must go at the end.
Here is what I have so far:
let insert_number (x: int) (l: int list): int list =
List.fold_right l ~f:(
fun cur -> fun acc ->
if x < cur then cur::x::accum
else cur::accum
) ~init: []
Using this with a test case like:
insert_number (3) ([1; 2; 4]);;
- : int list = [1; 2; 3; 4]
gives the correct answer. However, with a test case like this:
insert_number (3) ([1; 2]);;
- : int list = [1; 2]
the number is not inserted because it should be added to the end of the list.
Could someone help me understand how I am supposed to integrate this case into the function used with List.fold_right.
A fold works by passing along a set of state as it iterates over each element in a list (or other foldable data structure). The function passed in takes both the current element and that state.
I think you're really really close, but you need as Jeffrey suggests a boolean flag to indicate whether or not the value has been inserted. This will prevent multiple insertions and if the flag is still false when the fold is done, we can detect that and add the value to insert.
This match also serves the purpose of giving us an opportunity to discard the no longer needed boolean flag.
let insert v lst =
match List.fold_right
(fun x (inserted, acc) ->
if v > x && not inserted then (true, x::v::acc)
else (inserted, x::acc))
lst
(false, []) with
| (true, lst) -> lst
| (_, lst) -> v::lst
One way to look at List.fold_right is that it looks at each element of the list in turn, but in reverse order. For each element it transforms the current accumulated result to a new one.
Thinking backward from the end of the list, what you want to do, in essence, is look for the first element of the list that's less than x, then insert x at that point.
So the core of the code might look something like this:
if element < x then element :: x :: accum else element :: accum
However, all the earlier elements of the list will also be less than x. So (it seems to me) you need to keep track of whether you've inserted x into the list or not. This makes the accumulated state a little more complicated.
I coded this up and it works for me after fixing up the case where x goes at the front of the list.
Perhaps there is a simpler way to get it to work, but I couldn't come up with one.
As I alluded to in a comment, it's possible to avoid the extra state and post-processing by always inserting the element and effectively doing a "local sort" of the last two elements:
let insert_number x l =
List.fold_right (
fun cur -> function
| [] when x > cur -> [cur; x]
| [] -> [x; cur]
| x::rest when x > cur -> cur::x::rest
| x::rest -> x::cur::rest
) l []
Also, since folding doesn't seem to actually be a requirement, here's a version using simple recursion instead, which I think is far more comprehensible:
let rec insert_number x = function
| [] -> [x]
| cur::rest when cur > x -> x::cur::rest
| cur::rest -> cur::insert_number x rest

Changin list which is an iput with function

Good morning,
I have a problem with coding using ocaml so I had to code a function that take on input list then add to this list an element.
But using this does'nt affect the list1 so how can I do this ?
Thank you.
let rec append list1 element list2 = match list2 with
[]-> list1
| e::l -> if ( element = e ) then e :: list1
else (append list1 element l)
;;
List are immutable in OCaml, you can't change this. You can write a function append that takes a list and returns a new list that appends an element to it.
For example, here is the prepend function that takes a list and an element and returns a new list with the given element prepended to the passed list,
let prepend xs x = x :: xs
The append function is a little bit trickier, since lists in OCaml are singly-linked, so it is easy to prepend but hard to append. To implement the append function you need an intermediate list, let's call it acc for accumulator. You then go through each element of the input list and add it to the accumulator. Since you're prepending, then once the input list is over your accumulator will have all the elements of the input list by in the reversed order, i.e., the first element (aka the head) of the acc list will be the last element of the input list. Now you what is left is to prepend the element that we want to append to the reversed acc list and reverse act. Here is the skeleton code for you
let append xs x =
let rec loop xs acc = match xs with
| ... -> ... in
loop xs []

Accessing specific elements in a list of tuples in f# without libraries

I have a list of tuples with three different elements like so:
[(a0:string, b0:string, c0:int); (a1, b1, c1); (and so on...)].
I need to make a function that takes this list and a "name" in the form of a and gives a list of all the bs where the name matches the a in the tuple. But I'm not sure how to iterate and match everything.
input: function name tuplelist
output: [b0 if a0 = name; b1 if a1 = name; b2 if a2 = name]
I also cannot use libraries!!!
When writing code in a functional style you will often use recursion, if not explicitly then implicitly since most list/array/sequence functions all use recursion under the hood.
In F#, you need to explicitly state that a function is recursive, so the function you create will use the let rec syntax in its definition. Given your requirements, your function will probably look like this:
let rec myFilter (name: string) (input: (string * string * int) list) =
...
For this class of problems, where you iterate over a list recursively, you usually use pattern matching to check if you are at the end of a list, and if so, return an empty list.
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
...
Now you need to write a pattern match that checks the first item in the tuple against the supplied name. You can use pattern matching on the head of the list, and F#'s when syntax to deconstruct the head of the list for comparison
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
| ((a, b, _) :: rest) when a = name -> b :: myFilter name rest
...
This second case matches when a matches the queried name. When it matches, it will return a new list of which b is the head of the list, and then it will take the rest of the list of tuples and call myFilter recursively. This is how you iterate through the list recursively.
We have one more case to check for: If we don't find a match, we want to keep stepping through the list without collecting b. This can be expressed by peeling off the head and recursively calling myFilter, sending only the rest of the tuples.
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
| ((a, b, _) :: rest) when a = name -> b :: myFilter name rest
| (_ :: rest) -> myFilter name rest
Calling myFilter "a" [("a","x",3);("b","y",4);("a","z",5)] then yields ["x"; "z"], as expected.
Powerful F# pattern matching and recursion along with type inference easily compensate for dropping libraries limitation.
You need to build a map function converting one list into another list, this is to be addressed with recursion, the mapping function applied to each element of the list may use pattern matching to disassemble tuple into components and perform the conversion.
Something like the following will do:
let filter name (tupleList:(string*string*int) list) =
let checkElement name = function | (a,b,c) -> if a = name then Some b else None
let rec mapList name inputList outputList =
match inputList with
| [] -> outputList
| h::t -> let filter = checkElement name h
mapList name t (if filter = None then outputList else (outputList # [filter.Value]))
mapList name tupleList []
Here checkElement is the mapping function that takes the name and a tuple (a,b,c) and returns an option value either Some b if a = name, or None if not.
Recursive function mapList on each step operates with the unprocessed part of inputList of tuples and outputList accumulating on each recursion step parts from matched elements only. On each recursion step it checks if the inputList is empty. If yes, then we are done and it's time to return the accumulated result, otherwise we split the head element off inputList and apply the mapping function to it, changing the accumulated list, if this is the case. Then we do the next recursion step on the tail of inputList and the accumulator.
This task requires you to write your own recursive list processing function. I was able to implement it by using two sub-functions.
While the answers by #GeneBelitski and #ChadGilbert are great for learning, they are not tail-recursive, so I'll add my own.
Sub-function aux takes an accumulator and the list to process, and matches against the shape of the list. If it is empty, it returns the result accumulated so far. If it is a 3-tuple with a tail, it compares the first element to name, and if they are equal, continues running itself prepending the second element to the results accumulated, and the tail of the original list, otherwise just the results accumulated so far, and the tail of the original list.
As this way of accumulating results inverts the order of the resulting list, we need to reverse it before returning it; this is what the sub-function rev does, and as you see, the code looks almost identical to aux, prepending elements to the results accumulated so far but without doing any comparing or processing.
let filter_b name lst =
let rec aux acc = function
| [] -> acc
| (a : string, b : string, c : int) :: tl ->
if a = name
then aux (b :: acc) tl
else aux acc tl
let rec rev acc = function
| [] -> acc
| hd :: tl -> rev (hd :: acc) tl
lst
|> aux [] // process list with aux function
|> rev [] // reverse resulting list

Remove from list f#

I've been working this evening with lists in f# (creating, adding, searching etc) and have recently gotten stuck on a list item delete. The code is pretty straight forward.
let menu = [("pizza",17);("hotdog",5);("burger", 12);("drink",3);
("milkshake",4)]
//If key is in dictionary , return new dictionary with value removed
//otherwise return dictionary unchanged
let rec remove dict key =
match dict with
//if the list is empty, return an empty list
| [] -> []
//if the list is not empty and the head meets the removing criteria
//return a list obtained by reiterating the algorithm on the tail
//of the list
| (k,v) :: tl when k = key -> tl :: remove tl key
//if the list is not empty and the head does not meet the removing criteria
//return a list obtained by appending the head to a list obtained by
//reiterating algorithm on tail of the list
| (k,v) :: tl -> (k,v) :: remove tl key
The error comes from the final line of the function, | (k,v) :: tl -> (k,v) :: remove tl key. Apparently, it doesn't recognize (k,v) as the head of the list, and instead only sees a tuple with values. It makes sense, I don't know what else I would expect, but the problem is I don't know how to fix it. I tried putting the tuple inside of a list, like [(k,v)] but that made things even worse. I even tried | hd :: tl -> hd :: remove tl key but I had the exact same issue. Every other function I have written has accepted hd and tl as lists in my pattern matching.
How can I resolve this problem?
The second guard is wrong. You are using the tail twice, and since you are using it in a cons operation as first parameter it doesn't type check (it expects a single element, not a list).
Change it to:
| (k,v) :: tl when k = key -> remove tl key
I see one other mistake that you are making. It's a conceptual mistake rather than a bug in your code, but it will lead to more bugs unless you understand your mistake. You wrote:
Every other function I have written has accepted hd and tl as lists in my pattern matching.
(Emphasis mine). Your mistake is in thinking that when you write hd :: tl, both hd and tl are lists. You're half right: tl is indeed a list in that syntax, but hd is a single item. Proof:
let theList = [1; 2; 3; 4; 5]
printfn "The list: %A" theList
// Prints "The list: [1; 2; 3; 4; 5]"
match theList with
| [] -> printfn "The list was empty"
| hd :: tl -> printfn "Head was %A and tail was %A" hd tl
// Prints "Head was 1 and tail was [2; 3; 4; 5]"
When you use the syntax hd :: tl in pattern-matching, it splits the list into the first item (the head) and the rest of the list (the tail). When you use the syntax hd :: tl in a normal expression (e.g., everywhere that isn't a pattern match), you are taking a list called tl and a single item called hd, and prepending that item to the list, resulting in a brand-new list that has one more item at the front than the previous list did.
The sentence I quoted would have been correct if you had written:
Every other function I have written has accepted tl as a list and hd as a list item in my pattern matching.
I hope this helps you understand F# lists better!

Gaining an Element from a List of Tuples in Haskell

So I have a list of tuples defined like so:
type Domino = (Int,Int)
data End = L|R
type Board = [Domino]
d :: Domino
d= (4,5)
b :: Board
b= [(1,3),(3,3),(3,4)]
In my function I need to be able to gain the first part of the board. So for example I can head the board to get the domino (1,3) as a tuple but I've been trying to get the integer one from this and simply failing. I need to be able to compare that integer value. My question is simply how do you acquire the first part of a tuple in an a list as everything I have done and searched keeps failing. Apologies if this is really simple, I am new to haskell. This is my function code, obviously with a bunch of errors
goesP :: Domino->Board->End-> Bool
goesP _ []_ = True
goesP dom bor L = (if head bor fst == fst dom then True else if last bor == snd then True else False)
Something as simple as
goesP :: Domino -> Board -> End -> Bool
goesP _ [] _ = True
goesP _ ((a,b):doms) _ = a
will work, as you can pattern match for the list being empty, and then being a pair cons the rest of a list, and extract the first element out of that pair.
I'm not sure what you're trying to do with the End type in there as well, but I left it in there in my example (although I do nothing with it).
From your question, it doesn't look like you're interested in a generalised function, so these will work:
fst $ head b will get the very first Int in that list, and snd $ last b will get the very last.
How you compare them then is up to you.
As you may or may not know fst and snd only work for 2-element tuples so for you it should be enough:
fst (a,b) = a
You can also write you own:
get3th (_,_,a,_,_,_,_,_,_,_) = a
As you can see you may want to define your own type.