Swap key and value in a map in fsharp - dictionary

How to create a new map that is similar to the original one, but with swapped keys and values in Fsharp?
For example, I have this
let map1 =
[("A", "1"); ("B", "2"); ("C", "3");]
|> Map.ofList
and want to get this:
let map2 =
[("1", "A"); ("2", "B"); ("3", "C");]
|> Map.ofList
Thank you for your help!

Perhaps you will approach this decision:
let map1 = Map.ofList [("A", "1"); ("B", "2"); ("C", "3")]
map1 |> printfn "%A"
let rev map: Map<string,string> =
Map.fold (fun m key value -> m.Add(value,key)) Map.empty map
rev map1 |> printfn "%A"
Print:
map [("A", "1"); ("B", "2"); ("C", "3")]
map [("1", "A"); ("2", "B"); ("3", "C")]
Link: http://ideone.com/cfN2yH

You could convert it to a list and back, calling a function to swap in the middle.
let swap (x, y) = y, x
let swapAll tuples = List.map swap tuples
let invert map = map |> Map.toList |> swapAll |> Map.ofList
This method somewhat highlights what's nice about functional programming--you can build up complex behavior just by combining small building blocks.

Related

Removing from a list of a tuples that contains an empty element in the second projection F#

I need to learn the right way to do pattern matching on Pair types:
let pairToBeFiltered = Ok ([(1,[]);(2,[3;4]);(5,[6;7;8]);(9,[]);(10,[])])
let filterEmpty (pair: int * int list) =
match pair with
| (x,y) when y <> [] -> (x,y) //This gives error because of incomplete pattern matching!
let filtering = List.map(filterEmpty) pairToBeFiltered
Desired output:
Ok([(2,[3;4]);(5,[6;7;8])])
This should do it:
let pairsToBeFiltered = Ok ([(1,[]);(2,[3;4]);(5,[6;7;8]);(9,[]);(10,[])])
let filterEmpty pairs =
List.where (fun (_, y) -> y <> []) pairs // pattern match on pair occurs here
let filtering : Result<_, string> =
pairsToBeFiltered
|> Result.map filterEmpty
printfn "%A" filtering // Ok [(2, [3; 4]); (5, [6; 7; 8])]
There are a number of issues here:
For clarity, I modified filterEmpty so it processes the entire list, rather than a single pair. This is where we apply the filtering function, List.where, using pattern matching. (In your code, note that List.map with a match expression doesn't filter anything.)
Since your list is wrapped in a Result, you need to unwrap it via Result.map in order to process it. (Since you didn't specify a 'TError type, I assumed string to pacify the compiler.)
Three more versions:
(* using match statement *)
module Version1 =
let pairsToBeFiltered : Result<_, string> =
Ok [(1,[]);(2,[3;4]);(5,[6;7;8]);(9,[]);(10,[])]
let myWhere (pair : int * List<int>) =
match pair with
| _, [] -> false
| _, _ -> true
let myFilter l0 = l0 |> Result.map (List.filter myWhere)
let result = pairsToBeFiltered |> myFilter
(* using lambda functions and List.isEmpty *)
module Version2 =
let pairsToBeFiltered : Result<_, string> =
Ok [(1,[]);(2,[3;4]);(5,[6;7;8]);(9,[]);(10,[])]
let myFilter l0 =
l0
|> Result.map (fun l1 ->
l1 |> List.filter (fun (_, l2) ->
l2 |> List.isEmpty |> not))
let result = pairsToBeFiltered |> myFilter
(* shortening Version2 (point free style - take care, can be confusing) *)
module Version3 =
let pairsToBeFiltered : Result<_, string> =
Ok [(1,[]);(2,[3;4]);(5,[6;7;8]);(9,[]);(10,[])]
let myFilter = Result.map (List.filter (snd >> List.isEmpty >> not))
let result = pairsToBeFiltered |> myFilter

F# continuation recursion bug

I'm having an issue with a recursive function that runs into a stack overflow on larger data sets so I've attempted to rewrite the function to use continuous recursion but to say I'm new to this would be an understatement. In the below example the first function, processList, gives the desired results on a small data set. The second function, processListCont, seems to work however I know there must be a bug since when I run the same small data set through it I get different results. Would processListCont be the correct way to express the processList function or am I missing something?
open System
type Something(id) =
member val id = id with get, set
member val children : list<Something> = [] with get, set
member val processed : bool = false with get, set
let rec processList (item:Something, itemList:list<Something>) =
for child in item.children do
let parent = itemList |> Seq.find (fun (i:Something) -> i.id = child.id)
if parent.processed = false then
parent.processed <- true
processList(parent, itemList)
let processListCont (item:Something, itemList:list<Something>) =
let rec _processListCont (item:Something, itemList:list<Something>, f) =
for child in item.children do
let parent = itemList |> Seq.find (fun (i:Something) -> i.id = child.id)
if parent.processed = false then
parent.processed <- true
f(parent, itemList)
_processListCont(item, itemList, (fun (item:Something, itemList:list<Something>) -> ()))
[<EntryPoint>]
let main argv =
// generate some data
let count = 10000
let idList = List.init count (fun index -> index)
let items = [for (id) in idList -> Something id]
let rnd = System.Random()
for i in items do
i.children <- List.init 100 (fun _ -> Something (rnd.Next(0, count - 1)))
// process the list
for i in items do
processList(i, items)
Console.WriteLine("Processing completed successfully")
Console.ReadKey()
|> ignore
0
The main issue is that you are calling the continuation f in the body of the for loop, but your non-tail-recursive version makes a recurisve call here.
This is tricky because you want to make a recursive call and the continuation should be "run the rest of the for loop". To express this, you'll need to use pattern matching instead of for loop.
I did not have a small example to test this, but I think something like this should do the trick:
let rec processListCont (item:Something, itemList:list<Something>) cont =
let rec loop (children:list<Something>) cont =
match children with
| child::tail ->
let parent = itemList |> Seq.find (fun (i:Something) -> i.id = child.id)
if parent.processed = false then
parent.processed <- true
processListCont (parent, itemList) (fun () -> loop tail cont)
| [] -> cont ()
loop item.children cont
Your code is unidiomatic in F# nonetheless consider the following example.
Suppose you want to add a list of numbers. You could write a function like this:
let rec add (l:int list) :int =
match l with
| [] -> 0
| x::xs -> x + (add xs)
but this would overflow the stack very quickly. Instead you could use cps to allow the code to become tail recursive:
type
cont = int -> int
let rec add2 (l:int list) (k:cont):int =
match l with
| [] -> k 0
| x::xs -> add2 xs (fun a -> k (a + x))
which you can use like this:
printfn "%i" (add2 [1..10000] id)
In a similar fashion you could rewrite your function like this:
type cont2 = Something list->unit
let rec p (item:Something, itemList:list<Something>) (k:cont2) =
match item.children with
| [] -> k []
| child::xs ->
let parent = itemList |> Seq.find (fun (i:Something) -> i.id = child.id)
if parent.processed = false then
parent.processed <- true
p (parent, itemList) (fun _ ->k xs)
else
k xs
let p2 (item:Something,itemList:Something list) = p (item,itemList) ignore
and you can call it like this:
for i in items do
p2(i, items)

Already existing high-order function for this algorithm?

I've come up with this simple algorithm (convert list of tuples to a map collection of keys to lists) that I needed in my F# code:
let MergeIntoMap<'K,'V when 'K: comparison>(from: seq<'K*'V>): Map<'K,seq<'V>>=
let keys = from.Select(fun (k,v) -> k)
let keyValuePairs = seq {
for key in keys do
let valsForKey = from.Where(fun (k,v) -> key = k).Select(fun (k,v) -> v) |> seq
yield key,valsForKey
}
keyValuePairs |> Map.ofSeq
Example input:
[ ("a", 1); ("b", 2), ("a", 3) ]
Output:
dict [ ("a", [1; 3]), ("b", [2]) ]
And I was thinking this must be something that is already in the BCL or F#'s set of high order functions maybe? If yes, can someone reference me to it? Because I'm sure my code is not very efficient as it is...
It seems you want to get something like that
let toGroupMap x =
x
|> Seq.groupBy fst
|> Seq.map
(fun (k,v) -> k, v |> Seq.map snd |> Seq.toArray)
|> Map.ofSeq
fsi:
val toGroupMap : x:seq<'a * 'b> -> Map<'a,'b []> when 'a : comparison
val input : (string * int) list = [("a", 1); ("b", 2); ("a", 3)]
val output : Map<string,int []> = map [("a", [|1; 3|]); ("b", [|2|])]
Edit
As written Fyodor Soikin in the comments, there is a extension method ToLookup, which probably does what you need.
open System.Linq
let output = input.ToLookup(fst, snd)
You can read here about the difference between ILookup and IDictionary interfaces

How to create a dataframe of multiple types with the RTypeProvider

It seems like the RTypeProvider can only handle namedParams of the same type. Is this the case?
For example,
open RDotNet
open RProvider
type foo = {
Which: string
Qty: float option
}
let someFoos = [{Which = "that"; Qty = Some 4.0}; {Which = "other"; Qty = Some 2.0}]
let thingForR =
namedParams [
"which", someFoos |> List.map (fun x -> x.Which);
"qty", someFoos |> List.map (fun x -> x.Qty);
]
|> R.data_frame
doesn't work as I get an error on the x.Qty saying
This expression was expected to have type
string
but here has type
float option
If I reverse the order in the thingForR let, then I get the opposite error:
let thingForR =
namedParams [
"qty", someFoos |> List.map (fun x -> x.Qty);
"which", someFoos |> List.map (fun x -> x.Which);
]
|> R.data_frame
Here, the error on x.Which is
This expression was expected to have type
float option
but here has type
string
Can the dictionary in the namedParams not have different types? If so, how can you create a data frame with different types in F# and pass them to R?
You need to box the values inside the dictionary. That way they are all just object. So:
let thingForR =
namedParams [
"which", box (someFoos |> List.map (fun x -> x.Which) );
"qty", box (someFoos |> List.map (fun x -> x.Qty) |> List.map (Option.toNullable >> float));
]
|> R.data_frame
gives me:
val thingForR :
SymbolicExpression = which qty
1 that 4
2 other 2
Please refer to your previous question on float option to convert the Option list to float list. Also string option if necessary.
You can go through Deedle (if not for the option values):
let someFoos' = [{Which = "that"; Qty = 4.0}; {Which = "other"; Qty = 2.0}]
let df' = someFoos' |> Frame.ofRecords
df' |> R.data_frame

How do I printf a map in OCaml?

open Map
open Pretty
let d_doc () (x : doc) : doc = x
let d_str () = text
let d_map d_k d_v () m : doc =
printf "{%a}"
d_doc
(Map.fold (fun k v acc -> printf "%a, %a -> %a" d_doc acc d_k k d_v v) m (text ""))
tells me "Error: Unbound value Map.fold". How do I do this? (I'd like either a pointer to a reference that explains how to use Map functions (or module functions in general), a standard library pretty printer for maps, and/or a fix for my code.)
I realize this post is old, but for the future visitor, the following works:
module IntMap = Map.Make(Int)
type map = string IntMap.t
let pp_map ppf (m : map) =
IntMap.iter (fun k v -> Format.fprintf ppf "%d -> %s#\n" k v) m
let _ =
IntMap.empty
|> IntMap.add 4 "hello"
|> IntMap.add 2 "world"
|> Format.printf "%a" pp_map
You can print out a map using sexplib quite conveniently. Here's how you'd do it using Core.
open Core.Std
let map = Int.Map.of_alist_exn [1,"one"; 2,"two"; 3,"three"]
let () =
(<:sexp_of<string Int.Map.t>> map)
|> Sexp.to_string_hum
|> print_endline

Resources