real basic question here: I'm new to Ocaml and I'm having issues trying to manipulate lists. I've read http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html, and I'm unfortunately still confused....I'm new to functional programming.
If I have, say, the following function:
let stoverfl list1 list2 list3 =
match list1 with
|[]->None
|h::list1 -> (*what I want to do goes in here*)
I want to take a look at the first elements of list2 and list3, compare them, and if they're equal, add the first element of list3 to list2, else don't modify the lists. I don't really care about error checking now (i.e. checking to see if the list has at least one element, etc.).
My attempt:
h::list1 -> let cmp1 = hd list2 (*this should return the first elemnt of list2??*)
let cmp2 = hd list3
if(cmp1=cmp2) then
let updlist2 = concat list2 hd list3
let updlist3 = hd list3
(*pass updlist2 and updlist3 instead of list2 and list3 to next function*)
else
(*do nothing; pass list2 and list3 as normal*)
I feel like I'm doing it all wrong...any advice would be appreciated!
Thanks.
You say you want to add the first element of list3 to list2. When a functional programmer says something like this what it means is that they want to construct a new list as described. You can't actually modify list2--lists are immutable and names are permanently bound to a single value. In fact, it seems like you want to construct two new lists. One of them has the first element of list2 at the front of list3. The other one is the remainder of list2 (all but the first element).
Assuming this is what you mean, and assuming you're not worried whether the lists are empty, then here's one way to get these values:
let updlist2 = List.tl list2 in
let updlist3 = (List.hd list2) :: list3
It's actually pretty close to what you wrote.
However, I wonder what you're going to do with these values next. If you want to pass them along to another function, it would be more normal to have the lets outside the if. As an example, here's some code that calls a function g with either a list, or the tail of the list, depending on the first element of the list:
let arg_for_g =
match the_list with
| [] -> [] (* No tail of the list *)
| head :: tail -> if head = 3 then tail else the_list
in
g arg_for_g
If you put the lets inside the if, you'll need to code two different calls to your next function. That could be fine, it depends on exactly what you're going to do with your values.
(As a side note, you should worry about whether the lists are empty! If you use a match statement you can detect that case pretty easily.)
Related
I want to find a list of nodes that currently given nodes directly or indirectly connect to.
For example, I have a list of nodes:
[1,2]
and a list of tuples, and each of the tuples represents a direct edge:
[(1,5),(2,4),(4,6)]
So, the nodes I am looking for are
[1,2,5,4,6]
Because, 1 connects to 5, 2 connects to 4. Then, 4 is connected to 6.
To achieve this, I need two a queues, and a list. Each time a new node is discovered, we append the new node to the queue and the list. Then, we remove the first node of the queue, and go to next node. If a new node is connected to the current node of the queue. Then, we add new node to both the queue and the list.
We keep doing this until the queue is empty and we return the list.
So now, I have an append function which appends a list to another list:
fun append(xs, ys) =
case ys of
[] => xs
| (y::ys') => append(xs # [y], ys')
Then, I have a function called getIndirectNodes, which intends to return the lists of nodes that the given nodes indirectly connected to, but throws "unresolved flex record". List1 and List2 have the same items supposedly. But, List1 serves the queue, and list2 servers as the list to be returned.
fun getIndirectNode(listRoleTuples, list1, list2) =
if list1 = []
then list2
else if hd(list1) = #1(hd(listRoleTuples))
then (
append(list1,#2(hd(listRoleTuples)) :: []);
append(list2,#2(hd(listRoleTuples)) :: []);
getIndirectNode(listRoleTuples,tl(list1),list2)
)
else
getIndirectNode(listRoleTuples,tl(list1),list2)
If I remove the else if statement, it works perfectly fine. But, it's not what I intended to do. The problem is in the else if statement. What can I do to fix it?
SML needs to know exactly what shape a tuple has in order to deconstruct it.
You could specify the type of the parameter - listRoleTuples : (''a * ''a) list - but using pattern matching is a better idea.
(There are many other problems with that code, but that's the answer to your question.)
It seems that one of your classmates had this exact tuple problem in a very related task.
Make sure you browse the StackOverflow Q&A's before you ask the same question again.
As for getting the indirect nodes, this can be solved by fixed-point iteration.
First you get all the direct nodes, and then you get the direct nodes of the direct nodes.
And you do this recursively until no more new nodes occur this way.
fun getDirectNodes (startNode, edges) =
List.map #2 (List.filter (fn (node, _) => node = startNode) edges)
fun toSet xs =
... sort and remove duplicates ...
fun getReachableNodes (startNodes, edges) =
let
fun f startNode = getDirectNodes (startNode, edges)
val startNodes = toSet startNodes
val endNodes = toSet (List.concat (List.map f startNodes))
in
if startNodes = endNodes
then endNodes
else getReachableNodes (startNodes # endNodes, edges)
end
This doesn't exactly find indirect end-nodes; it finds all nodes directly or indirectly reachable by startNodes, and it includes startNodes themselves even if they're not directly or indirectly reachable by themselves.
I've tried to make this exercise easier by using sets as a datatype; it would be even neater with an actual, efficient implementation of a set type, e.g. using a balanced binary search tree. It is easier to see if there are no new nodes by adding elements to a set, since if a set already contains an element, it will be equivalent to itself before and after the addition of the element.
And I've tried to use higher-order functions when this makes sense. For example, given a list of things where I want to do the same thing on each element, List.map produces a list of results. But since that thing I want to do, getDirectNodes (startNode, edges) produces a list, then List.map f produces a list of lists. So List.concat collapses that into a single list.
List.concat (List.map f xs)
is a pretty common thing to do.
I'm trying to add an int list list with another int list list using the append function, but I can't get it to work the way I want.
Say that I want to append [[1,2,3,4,5]] with [6,7] so that I get [[1,2,3,4,5,6,7]].
Here's my attempt: [1,2,3,4,5]::[]#[6,7]::[], but it just gives me the list I want to append as a list of its own instead of the two lists combined into one, like this: [[1,2,3,4,5],[6,7]].
How can I re-write the operation to make it return [[1,2,3,4,5,6,7]]?
Your question is too unspecific. You are dealing with nested lists. Do you want to append the second list to every inner list of the nested list, or only the first one? Your example doesn't tell.
For the former:
fun appendAll xss ys = List.map (fn xs => xs # ys) xss
For the latter:
fun appendHd [] ys = raise Empty
| appendHd (xs::xss) ys = (xs # ys)::xss
However, both of these should rarely be needed, and I somehow feel that you are trying to solve the wrong problem if you end up there.
I have two lists of numbers. In each are the numbers [1,2,3,4] but in one there is an extra fifth number eg.
list1 = [1,2,3,4]
list2 = [1,2,3,4,5]
I need to enforce that list2 is the same as list1, by either removing the 5th number from list2 or replacing list2 with another copy of list1?
Can this be done?
This question is worded a bit strangely. If you're looking to mutate one of the lists, then the answer is no: that is not possible. Otherwise, you can of course just use list1 instead of list2 anywhere you need it.
Data.List provides the intersect method, which seems exactly what's being requested.
The most easy and performant way to enforce that list2 is the same as list1 would be to say
let list2 = list1 in .......
This would not even require that the list elements are comparable.
[ x | x <- list1, x `elem` list2 ]
and here's another one though I like Louis_Wasserman's solution most
filter (`elem` [1..4]) [1..12]
>>> [1,2,3,4]
or
filter (flip elem [1..4]) [1..12]
>>> [1,2,3,4]
fliter (\x ->x `elem` [1..4]) [1..12]
>>> [1,2,3,4]
if list two is irrelevant why do you use it in the first place ??
and another one came to my mind:
const [1..4] list2
>>> [1,2,3,4]
the last one just ignores the second list and fills in the first.
let rec filtersList2fromList1 (List1:string list) (List2:string list) : string list =
let finalList = [] in
match List1 with
| s :: tl -> if List.mem s List2 = true
then finalList # [s] else filtersList2fromList1 tl List2
| [] -> []
so that,
filtersList2fromList1 ["x";"y";"z"] ["z";"x"] would be ["x";"z"]
filtersList2fromList1 ["x";"y";"z"] ["x"] would be ["x"]
what I would like to add is, if the "if" statement is true, not only it would execute "finalList # [s]", but also "filtersList2fromList1 tl List2" so that it will be a recursion. Without executing "filtersList2fromList1 tl List2" when it is true,
filtersList2fromList1 ["x";"y";"z"] ["z";"x"] would only be ["x"], which is wrong.
How should I solve this problem?
Thank you very much
To answer your specific question, you'd either use a semi-colon or a let...in construct. In your case, neither will do what you want however.
You should read through the documentation on the standard library, as the List module contains everything you need to do what you want:
let filterList2fromList1 list1 list2 =
List.filter (fun x -> List.mem x list2) list1
Note that since you mentioned recursion, I'm assuming that when you wrote dolls_of you meant filtersList2fromList1. Also I'm assuming that List1 and List2 are supposed to be list1 and list2, since the former would be an error.
It should also be pointed out that # is an O(n) operation and it is not recommended to use it to build up lists. However as Niki pointed out in the comments, your use of finalList is pointless, so you don't actually need # anyway.
To answer your question: You can execute two expressions after another by separating them with a ;. However dolls_of is a function without side effects, so executing it without doing anything with its result would make little sense.
What you actually want to do, as far as I can tell, is:
if List.mem s list2
then s :: filtersList2fromList1 tl list2
else filtersList2fromList1 tl list2
how to get the value of the last element of a List? I've noted that List.hd (or .Head) return an item, while List.tl (or .Tail) returns a List.
Is rev the List and get the hd the only way around? Thanks.
Try this function. It uses recursion, though it gets optimised to iteration anyway since it's tail recursion. In any case, it is most likely quicker than reversing the entire list (using List.rev).
let rec last = function
| hd :: [] -> hd
| hd :: tl -> last tl
| _ -> failwith "Empty list."
The answer of Pavel Minaev is definitely worth taking into account, however. Nonetheless, the algorithm you have requested may be useful in some rare cases, and is the most efficient way to go about the task.
In general, if you need to do this, you're doing something wrong. Since F# lists are single-linked, accessing the last element is costly - O(N), where N is size of list. Try to rewrite your algorithm so that you always access the first element, not the last (which is O(1)). If you cannot do so, chances are good that your choice of list for a data structure wasn't correct in the first place.
A quick & dirty way of doing it is by using List.reduce. Assuming the list is called ls,
let lastElement ls = List.reduce (fun _ i -> i) ls
As for efficiency, I agree with Pavel.
A more concise version based on Mitch's answer:
let lastItem = myList |> List.rev |> List.head
The myList list is sent to List.rev function. The result is then processed by List.head
Agreed, not so efficient to get the last element of list, or any other "enumerable" sequence. That said, this function already exists in the Seq module, Seq.last.
As a novice F# developer, I don't see what the harm is in doing the following
let mylist = [1;2;3;4;5]
let lastValue = mylist.[mylist.Length - 1]
Imperative in nature? Yes but no need for recursion.
The regular way to work with lists in F# is to use recursion. The first item in a list is the head (obviously) and the rest of the list is the tail (as oppose to the last item). So when a function recieves a list it processes the head and then recursively processes the rest of the list (the tail).
let reversedList = List.rev originalList
let tailItem = List.hd reversedList
I think you can just write
list.[0..list.Length-1]
You can call List.Head to get the first element of a list, such that the below expression evaluates to true:
let lst = [1;2;3;4;5]
List.head lst = 1
However, calling List.Tail will return every element in the list after the first element, such that the below expression is true:
let lst = [1;2;3;4;5]
List.tail lst = [2;3;4;5]
Like some other people have mentioned, there isn't an efficient way in F# to get the tail end of a list, basic lists just aren't built with that functionality in mind. If you really want to get the last element you're going to have to reverse your list first, and then take the new head (which was the previous tail).
let lst = [1;2;3;4;5]
(List.head (List.rev lst) ) = 5
Below code worked fine with me, I've an array of integers, want to start from the 5th item, then take it minus the item number
Sum of [Array(xi) - Array(xi-5)] where i start at 5
The code used is:
series |> Array.windowed 5
|> Array.fold (fun s x ->
(x |> Array.rev |> Array.head) - (x |> Array.head) + s) 0
|> float
It's a very old question, but just in case someone comes here:
with FSharp 5, you can do x.[^index] where index will start at the end of the array / list.
let a = [1;2;3;4;5;6;7;8;9]
a.[^0] is 9
a.[^1] is 8
etc