I'm having a hard time incorporating Map.remove with a list of keys.
For example, if I have
let z : Map<int, Set<int>> = Map.ofList [(1, set []); (3, set [3; 4]); (4, set [])]
and I want to programmaticaly find each key, value in which the value is empty, I can do this:
let emptySets =
z
|> Map.toList
|> List.map (fun (k, s) -> (k, s |> Set.toList |> List.length))
|> List.filter (fun (k, i) -> i = 0)
|> List.map fst
This gives me
[1; 4]
which is exactly what I was expecting. But now, if I want to remove those key, value pairs from the map, the only way I can think of to do this is to convert the original Map into a list like this:
z
|> Map.toList
|> List.filter (fun (k, s) -> not (emptySets
|> List.contains k))
This gives me back the map I was expecting.
When I do this
emptySets
|> List.map (fun i -> Map.remove i z)
I get back a list of Maps.
Is there a way that I can use Map.remove to remove a list of keys from a given map without getting back a list of maps?
Every Map.remove call returns you a new map - identical to the "old" one, but without that one item. The old map is still intact, you can still use it, but if you continue to use it, you will still see the removed item, because it's still in the old map. If you want to perform next operations without the removed item, you have to perform those operations on the "new" map - the one returned from Map.remove, the one not containing the item.
let m0 = // create the map
let m1 = Map.remove 1 m0
let m2 = Map.remove 4 m1
Notice how each operation uses the result of the previous one. When you have a whole list of such operations, where each next one must use the result of the previous, thus "accumulating" the result in a sense, - that's called fold. The fold function takes three things: the initial accumulated value, a function that takes previous value and produces the next one, and the list of inputs:
let mapFinal= List.fold (fun mapPrev key -> Map.remove key mapPrev) mapInitial keys
Maybe I missed some point but couldn't it be easier to simply use Map.filter to keep the items where the value set isn't empty rather than removing all items where the value set is empty ?
Also it's a lot simpler to use Set.isEmpty rather than converting to list get it's length and checking if it's 0 or not.
Map.filter (fun _ -> not << Set.isEmpty) z
// val it : Map<int,Set<int>> = map [(3, set [3; 4])]
You can use a fold:
let z : Map<int, Set<int>> = Map.ofList [(1, set []); (3, set [3; 4]); (4, set [])]
let keysToRemove = [1;2]
List.fold (fun x i -> Map.remove i x) z keysToRemove
// val it : Map<int,Set<int>> = map [(3, set [3; 4]); (4, set [])]
Related
I have a situation where I'm parsing a file and I need to know both:
the current line
the previous line
before the previous line requirements, I was doing something like:
myData
|> List.mapi (fun i data -> parse i data)
but now I need access to the previous line, so scan is ideal for that, but then I loose the index.
so, I need a List.scani function :) is it something that could be built easily in an idiomatic way?
You could define scani as follows:
let scani (f:int->'S->'T->'S) (state:'S) (list:'T list) =
list
|>List.scan (fun (i,s) x -> (i+1,f i s x)) (0,state)
|>List.map snd
Creating a tuple with the original state and a counter initialized with (0,state). The state is manipulated as usual with the folder function f (that now takes an extra i parameter) and the counter incremented by one. Finally, we remove the counter from the state by taking the second element of the state.
You could use it as follows, where i is the index, s is the state, and x the element.
[1;2;3]
|> scani (fun i s x -> s + i*x) 0
|> should equal [0;0;2;8]
It may not be the most efficient way to do it, but it seems to work (I called it scanl given that you want access to the previous element, or line):
let scanl f s l =
List.scan (fun (acc,elem0) elem1 -> (f acc elem0 elem1),elem1) (s,List.head l) l
|> List.map fst
Examples of usage:
let l = [1..5]
scanl (fun acc elem0 elem1 -> elem0,elem1) (0,0) l
//result: [(0, 0); (1, 1); (1, 2); (2, 3); (3, 4); (4, 5)]
The usual List.scan would give this:
List.scan (fun acc elem -> elem) 0 l
//result [0; 1; 2; 3; 4; 5]
So I want a function that receives an array of Tuple<int,int> and returns the same type but with different values.
What I want to do is a function that returns this kind of values:
f( [1,10; 2,20; 3,40; 4,70] ) = [2,10; 3,20; 4,30]
So as you can see, the first number is basically unchanged (except the 1st item is not picked), but the last number is the substraction of the current number with the previous number (20 - 10 = 10, 40 - 20 = 20, ...).
I've tried to come up with an algorithm in F# that doesn't involve mutability (using an accumulator for the previous value would mean I need a mutable variable), but I can't figure out. Is this possible?
Using built-in functions. In this case, you can use Seq.pairwise. The function takes a sequence of inputs and produces a sequence of pairs containing the previous value and the current value. Once you have the pairs, you can use Seq.map to transform the pairs into the results - in your case, take the ID of the current value and subtract the previous value from the current value:
input
|> Seq.pairwise
|> Seq.map (fun ((pid, pval), (nid, nval)) -> nid, nval-pval)
Note that the result is a sequence (IEnumerable<T>) rather than a list - simply because the Seq module contains a few more (useful) functions. You could convert it back to list using List.ofSeq.
Using explicit recursion. If your task did not fit one of the common patterns that are covered by some of the built-in functions, then the answer would be to use recursion (which, in general, replaces mutation in the functional style).
For completeness, the recursive version would look like this (this is not perfect, because it is not tail-recursive so it might cause stack overflow, but it demonstrates the idea):
let rec f list =
match list with
| (pid, pval)::(((nid, nval)::_) as tail) ->
(nid, nval-pval)::(f tail)
| _ -> []
This takes a list and looks at the first two elements of the list (pid, pval) and (nid, nval). Then it calculates the new value based on the two elements in (nid, nval-pval) and then it recursively processes the rest of the list (tail), skipping over the first element. If the list has one or fewer elements (the second case), then nothing is returned.
The tail-recursive version could be written using the "accumulator" trick. Instead of writing newValue::(recursiveCall ...) we accumulate the newly produced values in a list kept as an argument and then reverse it:
let rec f list acc =
match list with
| (pid, pval)::(((nid, nval)::_) as tail) ->
f tail ((nid, nval-pval)::acc)
| _ -> List.rev acc
Now you just need to call the function using f input [] to initialize the accumulator.
> let values = [(1, 10); (2, 20); (3, 40); (4, 70)];;
val values : (int * int) list = [(1, 10); (2, 20); (3, 40); (4, 70)]
> values
|> Seq.pairwise
|> Seq.map (fun ((x1, y1), (x2, y2)) -> (x2, y2 - y1))
|> Seq.toList;;
val it : (int * int) list = [(2, 10); (3, 20); (4, 30)]
Seq.pairwise gives you each element in a sequence as a pair, except the first element, which is only available as the predecessor of the second element.
For example:
> values |> Seq.pairwise |> Seq.toList;;
val it : ((int * int) * (int * int)) list =
[((1, 10), (2, 20)); ((2, 20), (3, 40)); ((3, 40), (4, 70))]
Second, Seq.map maps each of these pairs of pairs by using the desired algorithm.
Notice that this uses lazy evaluation - I only used Seq.ToList at the end to make the output more readable.
BTW, you can alternatively write the map function like this:
Seq.map (fun ((_, y1), (x2, y2)) -> (x2, y2 - y1))
Notice that instead of x1 is replaced with _ because the value isn't used.
Mark and Tomas have given really good solutions for the specific problem. Your question had a statement I think warrants a third answer, though:
(using an accumulator for the previous value would mean I need a mutable variable)
But this is actually not true! List.fold exists exactly to help you process lists with accumulators in a functional way. Here is how it looks:
let f xs = List.fold (fun (y, ys) (d, x) -> x, (d, x-y) :: ys)
(snd (List.head xs), [])
(List.tail xs)
|> snd |> List.rev
The accumulator here is the argument (y, ys) to the fun ... in the first line. We can see how the accumulator updates to the right of the ->: we accumulate both the previous element of the list x, as well as the new list we're constructing (d, x-y)::xs. We'll get that list in reverse order, so we reverse it in the end with List.rev.
Incidentally, List.fold is tail-recursive.
Of course, Tomas and Mark's solutions using Seq.pairwise are much neater for your particular problem, and you'd definitely want to use one of those in practice.
Whenever we need to create a sequence from another sequence, where one element in the output is a function of its predecessors, scan (docs) comes in handy:
[1,10; 2,20; 3,40; 4,70]
|> List.scan (fun ((accA, accB), prevB) (elA, elB) -> ((elA, elB-prevB), elB)) ((0, 0), 0)
|> Seq.skip 2
|> Seq.map fst
yields:
[(2, 10); (3, 20); (4, 30)]
I have a map X and I'm trying to get a set of the keys satisfying a certain condition, something like this:
Map.Keys X
|> Set.filter (fun x -> ...)
...but I cannot find the way to get the keys from F#'s Map collection.
Convert your map to sequence of tuples (key,value) first and then map it to a sequence of just keys:
map |> Map.toSeq |> Seq.map fst
FSI sample:
>Map.ofList[(1,"a");(2,"b")] |> Map.toSeq |> Seq.map fst;;
val it : seq<int> = seq [1; 2]
Or alternatively, as ordering of keys likely does not matter you may use more eager method returning the list of all keys. It is also not hard to make it into extension method keys of Microsoft.FSharp.Collections.Map module:
module Map =
let keys (m: Map<'Key, 'T>) =
Map.fold (fun keys key _ -> key::keys) [] m
In F# 6.0, Map collection has now a Keys property.
OLD ANSWER:
Most readable (and probably most efficient, due to not needing previous conversions to Seq or mapping) answer:
let Keys(map: Map<'K,'V>) =
seq {
for KeyValue(key,value) in map do
yield key
} |> Set.ofSeq
For a set of keys you could just do:
let keys<'k, 'v when 'k : comparison> (map : Map<'k, 'v>) =
Map.fold (fun s k _ -> Set.add k s) Set.empty map
I have the following demand: getting the array of tuples from the first array according to the elements’ appearance in the second array:
let totals = [| ("old1", "new1"); ("old2", "new2"); ("old3", "new3"); ("old4", "new4") |]
let changes = [| "new1"; "new4" |]
I want to have this:
let updates = [| ("old1", "new1"); ("old4", "new4") |]
If the both arrays totals and changes have the same length, then I think it is easy:
let updates = Array.zip changes totals
|> Array.choose(fun (a, B) -> if a = fst(B) then Some (B) else None)
Unfortunately, totals and changes have different number of elements; therefore, I can not find an easy way to get the elements I need.
The solution posted by pad is correct and will work fine for small number of elements in changes. However, it iterates over the array changes for every element in total, so it may be inefficient for large arrays.
As an alternative, you can turn changes into an F# set type which allows more efficient membership test:
// Create set containing 'changes'
let changesSet = Set.ofArray changes
// Filter totals where the second element is in 'changesSet'
totals |> Array.filter (fun (_, v) -> changesSet.Contains(v))
// Same thing using function composition
totals |> Array.filter (snd >> changesSet.Contains)
You should select pairs in totals which have second elements occur in changes:
let updates =
totals
|> Array.filter (fun (_, x) -> changes |> Array.exists (fun y -> y = x))
I've trying to learn F#. I'm a complete beginner, so this might be a walkover for you guys :)
I have the following function:
let removeEven l =
let n = List.length l;
let list_ = [];
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)}
for x in seq_ do
let list_ = list_ # [x];
list_;
It takes a list, and return a new list containing all the numbers, which is placed at an odd index in the original list, so removeEven [x1;x2;x3] = [x1;x3]
However, I get my already favourite error-message: Incomplete construct at or before this point in expression...
If I add a print to the end of the line, instead of list_:
...
print_any list_;
the problem is fixed. But I do not want to print the list, I want to return it!
What causes this? Why can't I return my list?
To answer your question first, the compiler complains because there is a problem inside the for loop. In F#, let serves to declare values (that are immutable and cannot be changed later in the program). It isn't a statement as in C# - let can be only used as part of another expression. For example:
let n = 10
n + n
Actually means that you want the n symbol to refer to the value 10 in the expression n + n. The problem with your code is that you're using let without any expression (probably because you want to use mutable variables):
for x in seq_ do
let list_ = list_ # [x] // This isn't assignment!
list_
The problematic line is an incomplete expression - using let in this way isn't allowed, because it doesn't contain any expression (the list_ value will not be accessed from any code). You can use mutable variable to correct your code:
let mutable list_ = [] // declared as 'mutable'
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)}
for x in seq_ do
list_ <- list_ # [x] // assignment using '<-'
Now, this should work, but it isn't really functional, because you're using imperative mutation. Moreover, appending elements using # is really inefficient thing to do in functional languages. So, if you want to make your code functional, you'll probably need to use different approach. Both of the other answers show a great approach, although I prefer the example by Joel, because indexing into a list (in the solution by Chaos) also isn't very functional (there is no pointer arithmetic, so it will be also slower).
Probably the most classical functional solution would be to use the List.fold function, which aggregates all elements of the list into a single result, walking from the left to the right:
[1;2;3;4;5]
|> List.fold (fun (flag, res) el ->
if flag then (not flag, el::res) else (not flag, res)) (true, [])
|> snd |> List.rev
Here, the state used during the aggregation is a Boolean flag specifying whether to include the next element (during each step, we flip the flag by returning not flag). The second element is the list aggregated so far (we add element by el::res only when the flag is set. After fold returns, we use snd to get the second element of the tuple (the aggregated list) and reverse it using List.rev, because it was collected in the reversed order (this is more efficient than appending to the end using res#[el]).
Edit: If I understand your requirements correctly, here's a version of your function done functional rather than imperative style, that removes elements with odd indexes.
let removeEven list =
list
|> Seq.mapi (fun i x -> (i, x))
|> Seq.filter (fun (i, x) -> i % 2 = 0)
|> Seq.map snd
|> List.ofSeq
> removeEven ['a'; 'b'; 'c'; 'd'];;
val it : char list = ['a'; 'c']
I think this is what you are looking for.
let removeEven list =
let maxIndex = (List.length list) - 1;
seq { for i in 0..2..maxIndex -> list.[i] }
|> Seq.toList
Tests
val removeEven : 'a list -> 'a list
> removeEven [1;2;3;4;5;6];;
val it : int list = [1; 3; 5]
> removeEven [1;2;3;4;5];;
val it : int list = [1; 3; 5]
> removeEven [1;2;3;4];;
val it : int list = [1; 3]
> removeEven [1;2;3];;
val it : int list = [1; 3]
> removeEven [1;2];;
val it : int list = [1]
> removeEven [1];;
val it : int list = [1]
You can try a pattern-matching approach. I haven't used F# in a while and I can't test things right now, but it would be something like this:
let rec curse sofar ls =
match ls with
| even :: odd :: tl -> curse (even :: sofar) tl
| even :: [] -> curse (even :: sofar) []
| [] -> List.rev sofar
curse [] [ 1; 2; 3; 4; 5 ]
This recursively picks off the even elements. I think. I would probably use Joel Mueller's approach though. I don't remember if there is an index-based filter function, but that would probably be the ideal to use, or to make if it doesn't exist in the libraries.
But in general lists aren't really meant as index-type things. That's what arrays are for. If you consider what kind of algorithm would require a list having its even elements removed, maybe it's possible that in the steps prior to this requirement, the elements can be paired up in tuples, like this:
[ (1,2); (3,4) ]
That would make it trivial to get the even-"indexed" elements out:
thelist |> List.map fst // take first element from each tuple
There's a variety of options if the input list isn't guaranteed to have an even number of elements.
Yet another alternative, which (by my reckoning) is slightly slower than Joel's, but it's shorter :)
let removeEven list =
list
|> Seq.mapi (fun i x -> (i, x))
|> Seq.choose (fun (i,x) -> if i % 2 = 0 then Some(x) else None)
|> List.ofSeq