From pseudo C#, I have this:
class C
{
List<A> a;
List<B> b;
}
List<C> L;
I would like to get to get two lists: ListA and ListB where ListA is the concatenation of all 'a' fields from the list L, and similar for ListB.
it would be something like:
var ListA = new List<A>();
var ListB = new List<B>();
foreach (var l in L)
{
ListA.Append(l.a);
ListB.Append(l.b);
}
In F#,
I assume it would be something like: let ListA = L |> List.Concat (but how do I say to pick the field a?)
or could it be done as a let ListA = L |> List.Fold (fun acc value -> acc.Concat value) (how do I specify the empty list here?)
or, can it be done like this?
let getElementsA (l : C list) =
seq {
for element in l do
for a in element.a do
yield a
}
but isn't that too verbose?
This is what List.collect, or Seq.collect for C# lists, is for:
let listA = l |> Seq.collect (fun element -> element.a) |> List.ofSeq
let listB = l |> Seq.collect (fun element -> element.b) |> List.ofSeq
Or if you really need to do it in one iteration you can use a fold:
let (seqA, seqB) =
l |> Seq.fold
(fun (seqA, seqB) element -> (Seq.append element.a seqA, Seq.append element.b seqB))
([], [])
You can use List.collect:
let getElementsA (cs : C list) = cs |> List.collect (fun c -> c.a)
if the property type is System.Collection.List<T> then you can use Seq.collect:
let getElementsA (cs : C list) = cs |> Seq.collect (fun c -> c.AS)
this returns a A seq which you can convert into a list using List.ofSeq:
let getElementsA (cs : C list) = cs |> Seq.collect (fun c -> c.AS) |> List.ofSeq
F# uses other lists, function objects (like delegates). You can find all that you need in Microsoft.FSharp namespace
If I have this code in F#.
A function that resives a list with action and return nothing (list:'a list -> action:('a -> unit) -> unit).
module FS =
let actLit list action =
list
|> List.iter (action)
For this on C#, include Microsoft.FSharp.Collections.ListModule module and call functions work with F# lists. ListModule.OfSeq(l) creates new F# list.
Microsoft.FSharp.Core.FunctionModule contains conversion methods.
After converting you can call it.
var a = new List<int> ();
var list = ListModule.OfSeq(a);
var func = FuncConvert.FromAction<int>(Console.WriteLine);
FS.actLit(list, func);
Related
If I have an input of a tuple containing two lists of integers of the same length, and I want my output to be a list of these two lists zipped, after extracting these two lists from the tuple how do I zip each individual element into one list? For example, if my input is twolists= ([1;2;3], [4;5;6]), then I want my output to be [(1,4); (2,5); (3,6)]. How do I zip each element and add it to my output?
The function name and type is as follows:
let rec pairlists twolists = ...
val pairlists : 'a list * 'b list -> ('a * 'b) list = fun
So far I have:
let rec pairlists twolists =
let (l1, l2) = twolists in
let rec zip (l1,l2) =
match l1 with
|[] -> l2
|x :: xs -> x :: zip(l2, xs) in
twolists ;;
but this is clearly not doing what I want.
Are you looking for List.combine ?
val combine : 'a list -> 'b list -> ('a * 'b) list
Transform a pair of lists into a list of pairs: combine [a1; ...; an] [b1; ...; bn] is [(a1,b1); ...; (an,bn)].
Raises Invalid_argument if the two lists have different lengths. Not tail-recursive.
If your result list should contain elements that consist of the elements of both sublists, then you obviously have to destructure each sublist on each iteration.
If the lists are guaranteed to have the same lengths, the solution can be as simple as:
let rec zip paired_lists =
match paired_lists with
| [], [] -> []
| h1::t1, h2::t2 -> (h1, h2)::(zip (t1, t2))
| _, _ -> failwith "oops, the lists seems to have different lengths"
;;
zip ([1;2;3], [4;5;6]);;
- : (int * int) list = [(1, 4); (2, 5); (3, 6)]
But this one is not tail-recursive, which is obviously not good. The second sub-optimal thing is this reconstruction of tuple of lists on each iteration (I'm a newbie in OCaml, so chances are compiler is smart enough to avoid the unnecessary allocations, but still...). Fixing both flaws is trivial too:
let zip_tr paired_lists =
let list1, list2 = paired_lists in
let rec aux l1 l2 acc =
match l1, l2 with
| [], [] -> List.rev acc
| h1::t1, h2::t2 -> aux t1 t2 (h1, h2)::acc
| _, _ -> failwith "oops, the lists seems to have different lengths"
in aux list1 list2 []
;;
zip_tr ([1;2;3], [4;5;6]);;
- : (int * int) list = [(1, 4); (2, 5); (3, 6)]
The signature of your code does not match the expected signature :
line 2, characters 11-13:
Warning 26: unused variable l2.
Line 2, characters 7-9:
Warning 26: unused variable l1.
val pairlists : 'a list * 'a list -> 'a list = <fun>
Indeed, both possible matches return either a 'a list (this is l2) or x::zip... which is also a list of 'a type.
There should be sth like (x,y)::list in your code.
In addition, pairlists is not recursive and does not need to be declared as such, only zip is recursive.
The end of your function shall be like this (otherwise zip has no effect) :
....
let rec zip (l1,l2) =
match l1 with
|[] -> l2
|x :: xs -> x :: zip(l2, xs) in
zip twolists ;;
In addition to the other solutions mentioned, ocaml-4.08 onwards enables you to provide let+ and and+ operators which will zip a list sum-wise, where you might otherwise think of using applicatives. Whether it is an improvement on them is in the eye of the beholder:
let (let+) list f = List.map f list
let (and+) a b =
let rec loop first second =
match first,second with
first_hd::first_tl,second_hd::second_tl ->
(first_hd,second_hd)::(loop first_tl second_tl)
| _ -> []
in
loop a b
let pairlists = function
first,second ->
let+ elt1 = first
and+ elt2 = second in
[elt1 ; elt2]
(* example *)
let () =
let res = pairlists ([1;2;3], [4;5;6]) in
List.iter
(fun list -> List.iter (fun i -> Printf.printf "%d " i) list ;
print_endline "")
res
Here by way of comparison is the more traditional approach if you are using applicatives
let pure x = [x]
let (<*>) aps args =
List.concat (List.map (fun f -> List.map (fun x -> f x) args) aps)
let (<|>) aps args =
let rec loop args_rest aps_rest =
match args_rest,aps_rest with
args_hd::args_tl,aps_hd::aps_tl ->
(aps_hd args_hd)::(loop args_tl aps_tl)
| _ -> []
in
loop args aps
let pairlists = function
first,second ->
let two_list a b = a :: [b] in
pure two_list <*> first <|> second
(* example *)
let () =
let res = pairlists ([1;2;3], [4;5;6]) in
List.iter
(fun list -> List.iter (fun i -> Printf.printf "%d " i) list ;
print_endline "")
res
fold_right gives me values starting from the tail of the list but I want to give a function to fold_right as a parameter such that this function would collect values starting from the head of the list .
I want iterto receive values starting with the head of the list.
Continous Passing is the keyword ... .Another way to ask the question would be how tofold_leftwith fold_right
let fold f ls acc = List.fold_right f ls acc
val iter : ('a -> unit) -> 'a t -> unit
let iter f my_type =
let rec iiter my_type return =
return (fold (fun x y -> f x) my_type ()) () in iiter my_type (fun x y -> ())
But when I call :
iter (fun a -> print_string a) ["hi";"how";"are";"you"];;
Output:
youarehowhi
I need
hihowareyou
This is quite simple, you must try to match the signatures for the behavior.
Iteration takes no input, and returns unit, while folding takes an input and returns an output of the same type. Now, if the input taken by folding is unit then you'll have a folding function which applies a function on each element of a collection by passing an additional unit and returning an unit, which basically corresponds to the normal iteration, eg:
# let foo = [1;2;3;4;5];;
# List.fold_left (fun _ a -> print_int a; ()) () foo;;
12345- : unit = ()
As you can see the fold function just ignores the first argument, and always returns unit.
let fold_left f init ls =
let res = List.fold_right (fun a b acc -> b (f acc a)) ls (fun a -> a)
in res init
now calling
fold_left (fun a b -> Printf.printf "%s\n" b) () ["how";"are";"you"];;
gives us
how
are
you
fold_left is like List.fold_left but constructed with List.fold_right (Not tail-recursive):
let fold_left f a l = List.fold_right (fun b a -> f a b) (List.rev l) a ;;
Is not a good idea, because fold_left is not tail-recursive and List.fold_left is tail-recursive. Is better to produce a fold_right (tail-recursive) as :
let fold_right f l a = List.fold_left (fun a b -> f b a) a (List.rev l) ;;
If you can't use List.rev :
let rev l =
let rec aux acc = function
| [] -> acc
| a::tl -> aux (a::acc) tl
in
aux [] l
;;
iter use fold_left :
let iter f op = ignore (fold_left (fun a b -> f b;a) [] op ) ;;
Test :
# fold_left (fun a b -> (int_of_string b)::a ) [] ["1";"3"];;
- : int list = [3; 1]
# rev [1;2;3];;
- : int list = [3; 2; 1]
# iter print_string ["hi";"how";"are";"you"];;
hihowareyou- : unit = ()
The continuation that you need to pass through fold in this case is a function that will, once called, iterate through the rest of the list.
EDIT: like so:
let iter f list = fold
(fun head iter_tail -> (fun () -> f head;; iter_tail ()))
list
()
I have two lists :
let a = ["a";"b"];
let b = ["c";"d"];
I want an output list c such as :
c = ["a";"c";"a";"d";"b";"c";"b";"d"];
How to do it in ocaml as lists are immutable? I am new to it.
You would return a new list. If you really are interested in the cartesian product of the lists, then this should be enough:
let cartesian l l' =
List.concat (List.map (fun e -> List.map (fun e' -> (e,e')) l') l)
# cartesian ["a";"b"] ["c";"d"];;
- : (string * string) list = [("a", "c"); ("a", "d"); ("b", "c"); ("b", "d")]
If you need that strange flat structure instead, you can use an additional list concatenation.
let flat_cartesian l l' =
List.concat (List.concat (
List.map (fun e -> List.map (fun e' -> [e;e']) l') l))
If you do not want to use concatenation, because this is not a tail recursive operation, you can use the following (which should be more efficient):
let product l1 l2 =
List.rev (
List.fold_left
(fun x a ->
List.fold_left
(fun y b ->
b::a::y
)
x
l2
)
[]
l1
)
;;
For the cartesian product, just change
b::a::y
into
(a,b)::y
I would break the problem into two sub problems:
Firstly consider a function appendeach with takes a value and a list and returns the result of adding that value infront of each item in the list
let rec appendeach x lst = match lst with [] -> []
| hd::tl -> x::hd::(appendeach x tl);;
Then consider a function product with takes two lists and calls appendeach for each item in the first list and the whole second list
let rec product lst1 lst2 = match lst1 with [] -> [] |
hd::tl -> (appendeach hd lst2)#(product tl lst2);;
Here's an implementation for any number of lists, based on Python's itertools.product.
The lists all have to be the same type, because the products we return will themselves be (necessarily homogenous) lists.
let product pools =
let result = ref [[]] in
List.iter (fun pool ->
result := List.concat_map (fun y ->
List.map (fun x ->
List.append x [y]
) !result
) pool
) pools;
!result
product [["a";"b"]; ["1";"2"]; ["$";"%"]];;
- : string list list =
[["a"; "1"; "$"]; ["b"; "1"; "$"]; ["a"; "2"; "$"]; ["b"; "2"; "$"];
["a"; "1"; "%"]; ["b"; "1"; "%"]; ["a"; "2"; "%"]; ["b"; "2"; "%"]]
If you then need a flattened list you can wrap it in List.concat as per the other answers:
List.concat (product [["a";"b"]; ["1";"2"]]);;
- : string list = ["a"; "1"; "b"; "1"; "a"; "2"; "b"; "2"]
A very imperative (java-like or C-like) solution so I'm not sure it will help; in functional languages like OCaml is usually expected recursion rather than loops. But it works:
let cartesianProduct list1 list2 =
let product = ref [] in
for i = 0 to List.length list1 -1 do
for j = 0 to List.length list2 -1 do
product:= !product#[List.nth list1 i]#[List.nth list2 j]
done;
done;
!product;;
Iam an F# newbie, I have following starting point:
type aB = { ID: int; Slide: list<string * int> }
// examples of aB's
let aB1 = { ID = 1; Slide = [("-10%",-20); ("0%",0); ("10%",20)] }
let aB2 = { ID = 2; Slide = [("-10%",6); ("0%",0); ("10%",3)] }
let correctoraB2 = {ID = 2; Slide = [("-10%", -2); ("0%", 0); ("10%", -1)] }
// Now we bunch the aB`s in a list together
let bunchedABRaw = [aB1; aB2; correctoraB2]
This list can now become quite long, in this list, I need now to first identify all the aB's with identical ID's, then I want to net out their slides, so that a new list results
let bunchedABReduced = [aB1; aB2New], where
aB2New = { ID = 2; Slide = [("-10%",4); ("0%",0); ("10%",2)] }
I am reading through the F# library on msdn but so far I don't know yet how to solve the problem, would be very happy for code proposition.
Thanks a lot
Martin
OK working my way through this when I have a minute.
Here's the first part where you can merge the slides of two aB's:
// this function can merge two slides
let mergeSlides l1 l2 =
List.zip l1 l2
|> List.map (fun ((a1, b1), (a2,b2)) -> (a1, b1+b2))
// see what it does
mergeSlides aB2.Slide correctoraB2.Slide
This bit groups all the aB's with the same Id:
let grp = bunchedABRaw
|> Seq.groupBy (fun a -> a.ID)
And now we can use mergeSlides as a folding function, that we use fold over each sequence of Ab's with the same Id to make the netted aB.
So here's the whole thing:
let mergeSlides l1 l2 =
List.zip l1 l2
|> List.map (fun ((a1, b1), (a2,b2)) -> (a1, b1+b2))
let net =
bunchedABRaw
|> Seq.groupBy (fun a -> a.ID)
|> Seq.map (fun (i, s) -> (i, s |> Seq.map (fun a -> a.Slide))) // strip away the slides
|> Seq.map (fun (i, s) -> (i, List.ofSeq s)) // turn seq<slide> into list<slide>
|> Seq.map (fun (i, l) -> (i, List.fold mergeSlides l.Head l.Tail)) // so we can use HEad and Tail
|> Seq.map (fun (i, l) -> {ID=i;Slide=l}) // and Project into aB
|> List.ofSeq // and then List
Enjoy!
Try this:
Set up a dictionary where the keys will be the IDs you encounter and the values will be a "netted" aB type for that ID.
Then run a fold* on the list using the dictionary as your state and have the function you fold across the list accumulate the items in the dictionary by ID ("netting" them as you go).
After that you can put all the dictionary's values into a return list.
If you can't "net" them as you go then you could store a list of items as values instead of a single "netted" value and then do the netting after the fold finishes.
*fold http://msdn.microsoft.com/en-us/library/ee353894.aspx
EDIT: Made some things clearer
I am new to F# and trying to figure out some basics but am stumbling along slowly. In the code below I am trying to generate a list of random integers and then sorting it.
let randomNumberList count =
let r = System.Random()
List.init count (fun _ -> r.Next(100))
let rec selectionSort l = function
| [] -> []
| l -> let min = List.min l in
let rest = List.filter (fun i -> i <> min) l in
let sortedList = selectionSort rest in
min :: sortedList
sortedList = selectionSort l
let unsortedList = randomNumberList 10
printfn "%A" unsortedList
printfn "%A" sortedList
So two things...one is the error I'm getting:
stdin(515,19): error FS0001: This expression was expected to have type
'a list
but here has type
'a list -> 'a list
The other is with the random number list. It works, but I want the numbers generated to be less than 100, instead of the massive values I'm getting now.
Thanks for your patience and help!
As mentioned in the comment, there is no need for l in let rec selectionSort. Fixed code:
let randomNumberList count =
let r = System.Random()
List.init count (fun _ -> r.Next(100))
let rec selectionSort = function
| [] -> []
| l -> let min = List.min l in
let rest = List.filter (fun i -> i <> min) l in
let sortedList = selectionSort rest in
min :: sortedList
let unsortedList = randomNumberList 10
let sortedList = selectionSort unsortedList
printfn "%A" unsortedList
printfn "%A" sortedList
System.Console.ReadLine() |> ignore
Explanation:
let vname = function
| ... -> ...
| ... -> ...
is the short form of
let vname arg = match arg with
| ... -> ...
| ... -> ...