Lets say I have a list containing and int* list of lists How would I be able to extract the value of the int from this type of list? You could pattern match for the head of the list or the tail but how would you extract the int?
You can always just make two pattern matches in a row
match [[1;2]; [3;4]] with
| (firstrow::_) -> (
match firstrow with ->
| (x :: _) -> x
| [] -> 0 )
| _ -> 42
Its also OK to write pattern matches with multiple levels.
match [[1;2]; [3;4]] with
| (x::_)::_ -> x
| ([]::_) -> 0
| _ -> 42
That said, you don't necessarily need to use pattern matching to access the list elements. You can also use List.map or one of the many other list-manipulation functions depending on what you are actually trying to do.
I don't understand which value you want to extract exactly, by let's say that you want to extract all integers in your int list list and don't want to write pattern matchings with multiple levels, you can first use the List.flatten function to obtain an int list and then do what ever you want to do:
let l = List.flatten [[1; 2]; [3; 4]] in (* l = [1; 2; 3; 4] *)
List.iter print_int l (* iter, map or any other function *)
if you think your list of lists as a matrix and you have the line column you want
List.nth col (List.nth ln matrix)
List.nth is nice to use in this case, with the info you got me i think this is what you want
Related
Hi I'm new to f# and I got this exercise I can't figure out:
"Implement a Function :"
let compress (l : List<'a>) : List<'a> = ...
That removes consecutive occurences of the same element in l. for example compressing [a;a;a;a;b;b;c] to [a;b;c]
I'm not allowed to use the built-in functions of f# and need to do this with pattern matching.
My current code (it's not much) :
let rec compress (l: List<'a>) : List<'a> =
match l with
| [] -> l
thanks for the help!
For any recursive function you need to consider: 1. the terminal case and 2. the general case. In your scenario:
the empty list []
non-empty list x::xs (where x represents the head of the list and xs the rest aka tail)
The other important aspect to consider when you build such a functions is to assume it works for a previous value. For example in the case of factorial, we assume the function already works for a previous scenario e.g. factorial of n-1.
let fact n =
match n with
| 0 | 1 -> 1
| _ -> n * fact (n-1)
I am very new to F# and functional programming in general, and would like to recursively create a function that takes a list, and doubles all elements.
This is what I used to search for a spacific element, but im not sure how exactly I can change it to do what I need.
let rec returnN n theList =
match n, theList with
| 0, (head::_) -> head
| _, (_::theList') -> returnN (n - 1) theList'
| _, [] -> invalidArg "n" "n is larger then list length"
let list1 = [5; 10; 15; 20; 50; 25; 30]
printfn "%d" (returnN 3 list1 )
Is there a way for me to augment this to do what I need to?
I would like to take you through the thinking process.
Step 1. I need a recursive function that takes a list and doubles all the elements:
So, let's implement this in a naive way:
let rec doubleAll list =
match list with
| [] -> []
| hd :: tl -> hd * 2 :: doubleAll tl
Hopefully this logic is quite simple:
If we have an empty list, we return another empty list.
If we have a list with at least one element, we double the element and then prepend that to the result of calling the doubleAll function on the tail of the list.
Step 2. Actually, there are two things going on here:
I want a function that lets me apply another function to each element of a list.
In this case, I want that function to be "multiply by 2".
So, now we have two functions, let's do a simple implementation like this:
let rec map f list =
match list with
| [] -> []
| hd :: tl -> f hd :: map f tl
let doubleAll list = map (fun x -> x * 2) list
Step 3. Actually, the idea of map is such a common one that it's already built into the F# standard library, see List.map
So, all we need to do is this:
let doubleAll list = List.map (fun x -> x * 2) list
. Write a function that takes an integer list and return sum of all elements of the list. If the list is empty then return None.
This is my code now:
let rec sum (xs: int list) =
match xs with
| [] -> None
| [x] -> Some x
| hd::tl -> let m = (hd + (sum tl)) in
Some m
;;
The problem is that I can't seem to find a way to add up the last element without getting an error.
This is my error.
Error: This expression has type int but an expression was expected of type 'a option.
Your recursive call to sum does indeed return an int option. You know this because you're the author of the function, and you coded it up to return that type :-) You can either write a helper function that returns an int, or you can extract the int from the return value of sum, something like this:
let tlsum =
match sum tl with
| None -> (* figure this part out *)
| Some n -> (* figure this part out *)
You can define the addition of two int option.
let sum l =
let (+) a b =
match (a,b) with
| (None,x) | (x,None) -> x
| (Some x,Some y) -> Some (x+y)
in
let convert a = Some a in
let opt_l=List.map convert l in
List.fold_left (+) None opt_l
Test
# sum [];;
- : int option = None
# sum [1;2];;
- : int option = Some 3
That looks like an assignment so I'll be vague:
The easiest way to do that is probably to first define a function of type int list -> int that returns the "normal" sum (with 0 for the empty case). That function will be recursive and 0 will correspond to the base case.
Then write another function of type int list -> int option that checks whether its argument is empty or not and does the right thing based on that.
Trying to write the recursion directly probably is not a good idea since there are two cases when you will need to handle []: when it's the only element in the list, and when it's at the end of a nonempty list.
Say I have lists like [1;2;3;4;5;6;9] and [1;2;3;9] and I want to write a pattern which captures lists which begin with 1 and end with 9, and also capture the values of the middle of the list. Is this possible to do with OCaml's pattern matching?
I've tried to write something like
match l with
| 1::middle::9
or
match l with
| 1::middle::9::[]
but I'm not sure that these are doing what I want, and are probably instead only matching 3 element lists. Is there an approach I can take to match things like this? Should I be using nested pattern matches?
There's no pattern that matches the end of a list, so there's no pattern like what you want. You can do two matches:
match l with
| 1 :: _ -> (
match List.rev l with
| 9 :: _ -> true
| _ -> false
)
| _ -> false
Finding the end of a list is a linear time operation. If your lists can be long, you might want to use a different data structure.
If you're just making checks on the first and last elements of a list, you may want to use conditional statements instead of pattern matching:
let is_valid l =
let open List in
let hd' = hd l in (* Get the first element of the list *)
let tl' = rev l |> hd in (* Get the last element of the list *)
if hd' = 1 && tl' = 9 then true else false
is_valid [1;2;3;4;5;6;9] (* bool = true *)
However, if you are trying to extract that middle pattern it may be worthwhile to use pattern matching. We can do something similar to what Jeffery suggested because of the reason he pointed out (pattern matching can't match the end of a list):
let is_valid l =
let open List in
match l with
| 1 :: mid -> (* `mid` holds list without the `1` *)
(match rev mid with (* `rev_mid` holds list without the 9 but reversed *)
| 9 :: rev_mid -> Some (rev rev_mid) (* reverse to get correct order *)
| _ -> None)
| _ -> None
is_valid [1;2;3;4;5;6;9] (* int list option = Some [2; 3; 4; 5; 6] *)
Then with this function, you can use it with simple pattern matching to look for the middle of valid lists:
match is_valid l with
| Some middle -> middle (* the middle of the list *)
| None -> [] (* nothing — list was invalid *)
I'm working with a list of lists in OCaml, and I'm trying to write a function that combines all of the lists that share the same head. This is what I have so far, and I make use of the List.hd built-in function, but not surprisingly, I'm getting the failure "hd" error:
let rec combineSameHead list nlist = match list with
| [] -> []#nlist
| h::t -> if List.hd h = List.hd (List.hd t)
then combineSameHead t nlist#uniq(h#(List.hd t))
else combineSameHead t nlist#h;;
So for example, if I have this list:
[[Sentence; Quiet]; [Sentence; Grunt]; [Sentence; Shout]]
I want to combine it into:
[[Sentence; Quiet; Grunt; Shout]]
The function uniq I wrote just removes all duplicates within a list. Please let me know how I would go about completing this. Thanks in advance!
For one thing, I generally avoid functions like List.hd, as pattern maching is usually clearer and less error-prone. In this case, your if can be replaced with guarded patterns (a when clause after the pattern). I think what is happening to cause your error is that your code fails when t is []; guarded patterns help avoid this by making the cases more explicit. So, you can do (x::xs)::(y::ys)::t when x = y as a clause in your match expression to check that the heads of the first two elements of the list are the same. It's not uncommon in OCaml to have several successive patterns which are identical except for guards.
Further things: you don't need []#nlist - it's the same as just writing nlist.
Also, it looks like your nlist#h and similar expressions are trying to concatenate lists before passing them to the recursive call; in OCaml, however, function application binds more tightly than any operator, so it actually appends the result of the recursive call to h.
I don't, off-hand, have a correct version of the function. But I would start by writing it with guarded patterns, and then see how far that gets you in working it out.
Your intended operation has a simple recursive description: recursively process the tail of your list, then perform an "insert" operation with the head which looks for a list that begins with the same head and, if found, inserts all elements but the head, and otherwise appends it at the end. You can then reverse the result to get your intended list of list.
In OCaml, this algorithm would look like this:
let process list =
let rec insert (head,tail) = function
| [] -> head :: tail
| h :: t ->
match h with
| hh :: tt when hh = head -> (hh :: (tail # t)) :: t
| _ -> h :: insert (head,tail) t
in
let rec aux = function
| [] -> []
| [] :: t -> aux t
| (head :: tail) :: t -> insert (head,tail) (aux t)
in
List.rev (aux list)
Consider using a Map or a hash table to keep track of the heads and the elements found for each head. The nlist auxiliary list isn't very helpful if lists with the same heads aren't adjacent, as in this example:
# combineSameHead [["A"; "a0"; "a1"]; ["B"; "b0"]; ["A"; "a2"]]
- : list (list string) = [["A"; "a0"; "a1"; "a2"]; ["B"; "b0"]]
I probably would have done something along the lines of what antonakos suggested. It would totally avoid the O(n) cost of searching in a list. You may also find that using a StringSet.t StringMap.t be easier on further processing. Of course, readability is paramount, and I still find this hold under that criteria.
module OrderedString =
struct
type t = string
let compare = Pervasives.compare
end
module StringMap = Map.Make (OrderedString)
module StringSet = Set.Make (OrderedString)
let merge_same_heads lsts =
let add_single map = function
| hd::tl when StringMap.mem hd map ->
let set = StringMap.find hd map in
let set = List.fold_right StringSet.add tl set in
StringMap.add hd set map
| hd::tl ->
let set = List.fold_right StringSet.add tl StringSet.empty in
StringMap.add hd set map
| [] ->
map
in
let map = List.fold_left add_single StringMap.empty lsts in
StringMap.fold (fun k v acc-> (k::(StringSet.elements v))::acc) map []
You can do a lot just using the standard library:
(* compares the head of a list to a supplied value. Used to partition a lists of lists *)
let partPred x = function h::_ -> h = x
| _ -> false
let rec combineHeads = function [] -> []
| []::t -> combineHeads t (* skip empty lists *)
| (hh::_ as h)::t -> let r, l = List.partition (partPred hh) t in (* split into lists with the same head as the first, and lists with different heads *)
(List.fold_left (fun x y -> x # (List.tl y)) h r)::(combineHeads l) (* combine all the lists with the same head, then recurse on the remaining lists *)
combineHeads [[1;2;3];[1;4;5;];[2;3;4];[1];[1;5;7];[2;5];[3;4;6]];;
- : int list list = [[1; 2; 3; 4; 5; 5; 7]; [2; 3; 4; 5]; [3; 4; 6]]
This won't be fast (partition, fold_left and concat are all O(n)) however.