Check if an element is within a sequence - f#

how to check if an element is contained within a sequence? I expected some Seq.contains, but i could not find it. Thanks
EDIT:
Or, for an easier task, how to make the diff between two sequences? Like, getting all the elements within a list that doesn not belong to another (or that do)?

Little bit simpler:
let contains x = Seq.exists ((=) x)

Seq.exists
let testseq = seq [ 1; 2; 3; 4 ]
let equalsTwo n = (n = 2)
let containsTwo = Seq.exists equalsTwo testseq

Set is your friend here:
let a = set [0;1;2;3]
let b = set [2;3;4;5]
let c = a - b
let d = b - a
let e = Set.intersect a b
let f = a + b
>
val c : Set<int> = seq [0; 1]
val d : Set<int> = seq [4; 5]
val e : Set<int> = seq [2; 3]
val f : Set<int> = seq [0; 1; 2; 3; ...]
Danny

Seq.exists again, but with slightly different syntax -
let testseq = seq [ 1; 2; 3; 4 ]
let testn = 2
testseq |> Seq.exists (fun x -> x = testn)
See MSDN F#: Seq.exists function: https://msdn.microsoft.com/en-us/library/ee353562.aspx
Lots of other good ones there too!

(Another question, another answer.)
This works, but I don't think that it's the most idomatic way to do it - (you'll need to wait until the US wakes up to find out):
let s1 = seq [ 1; 2; 3; 4 ]
let s2 = seq [ 3; 4; 5; 6 ]
seq {
for a in s1 do
if not (Seq.exists (fun n -> n = a) s2) then
yield a
}

Related

Is there a way in f# to perform a cross operation on lists?

Is there a way in f# to perform an opreation on the all the possible element combinations of two lists in f#?
Example
l1 = [1;2;3]
l2=[4;5;6]
let plus x y = x+y
Then fun plus l1 l2 would perform [(1+4);(1+5);(1+6);(2+4);(2+5);(2+6);(3+4);(3+5);(3+6)]
Hence the output: [5;6;7;6;7;8;7;8;9]
Note: I have tried using zip but it only takes each element once.
Yep, easiest way is to use a list comprehension.
let t1 = [1;2;3]
let t2 = [4;5;6]
[for a in t1 do for b in t2 do yield a+b] //val it : int list = [5; 6; 7; 6; 7; 8; 7; 8; 9]
//as a function
let f lst1 lst2 = [for a in lst1 do for b in lst2 do yield a+b]
Another possibility is to combine a List.collect with a List.map:
let l1 = [1;2;3]
let l2 = [4;5;6]
l1 |> List.collect (fun x -> List.map ((+) x) l2) //output: [5; 6; 7; 6; 7; 8; 7; 8; 9]

f# sequence of running total

Ok, this looks like it should be easy, but I'm just not getting it. If I have a sequence of numbers, how do I generate a new sequence made up of the running totals? eg for a sequence [1;2;3;4], I want to map it to [1;3;6;10]. In a suitably functional way.
Use List.scan:
let runningTotal = List.scan (+) 0 >> List.tail
[1; 2; 3; 4]
|> runningTotal
|> printfn "%A"
Seq.scan-based implementation:
let runningTotal seq' = (Seq.head seq', Seq.skip 1 seq') ||> Seq.scan (+)
{ 1..4 }
|> runningTotal
|> printfn "%A"
Another variation using Seq.scan (Seq.skip 1 gets rid of the leading zero):
> {1..4} |> Seq.scan (+) 0 |> Seq.skip 1;;
val it : seq<int> = seq [1; 3; 6; 10]
> Seq.scan (fun acc n -> acc + n) 0 [1;2;3;4];;
val it : seq<int> = seq [0; 1; 3; 6; ...]
With lists:
> [1;2;3;4] |> List.scan (fun acc n -> acc + n) 0 |> List.tail;;
val it : int list = [1; 3; 6; 10]
Edit: Another way with sequences:
let sum s = seq {
let x = ref 0
for i in s do
x := !x + i
yield !x
}
Yes, there's a mutable variable, but I find it more readable (if you want to get rid of the leading 0).
Figured it was worthwhile to share how to do this with Record Types in case that's also what you came here looking for.
Below is a fictitious example demonstrating the concept using runner laps around a track.
type Split = double
type Lap = { Num : int; Split : Split }
type RunnerLap = { Lap : Lap; TotalTime : double }
let lap1 = { Num = 1; Split = 1.23 }
let lap2 = { Num = 2; Split = 1.13 }
let lap3 = { Num = 3; Split = 1.03 }
let laps = [lap1;lap2;lap3]
let runnerLapsAccumulator =
Seq.scan
(fun rl l -> { rl with Lap = l; TotalTime = rl.TotalTime + l.Split }) // acumulator
{ Lap = { Num = 0; Split = 0.0 }; TotalTime = 0.0 } // initial state
let runnerLaps = laps |> runnerLapsAccumulator
printfn "%A" runnerLaps
Not sure this is the best way but it should do the trick
let input = [1; 2; 3; 4]
let runningTotal =
(input, 0)
|> Seq.unfold (fun (list, total) ->
match list with
| [] ->
None
| h::t ->
let total = total + h
total, (t, total) |> Some)
|> List.ofSeq

F# split sequence into sub lists on every nth element

Say I have a sequence of 100 elements. Every 10th element I want a new list of the previous 10 elements. In this case I will end up with a list of 10 sublists.
Seq.take(10) looks promising, how can I repeatedly call it to return a list of lists?
now there's Seq.chunkBySize available:
[1;2;3;4;5] |> Seq.chunkBySize 2 = seq [[|1; 2|]; [|3; 4|]; [|5|]]
This is not bad:
let splitEach n s =
seq {
let r = ResizeArray<_>()
for x in s do
r.Add(x)
if r.Count = n then
yield r.ToArray()
r.Clear()
if r.Count <> 0 then
yield r.ToArray()
}
let s = splitEach 5 [1..17]
for a in s do
printfn "%A" a
(*
[|1; 2; 3; 4; 5|]
[|6; 7; 8; 9; 10|]
[|11; 12; 13; 14; 15|]
[|16; 17|]
*)
I have an evolution of three solutions. None of them preserves the ordering of the input elements, which is hopefully OK.
My first solution is quite ugly (making use of ref cells):
//[[4; 3; 2; 1; 0]; [9; 8; 7; 6; 5]; [14; 13; 12; 11; 10]; [17; 16; 15]]
let solution1 =
let split s n =
let i = ref 0
let lst = ref []
seq {
for item in s do
if !i = n then
yield !lst
lst := [item]
i := 1
else
lst := item::(!lst)
i := !i+1
yield !lst
} |> Seq.toList
split {0..17} 5
My second solution factors out the use of ref cells in the first solution, but consequently forces the use of direct IEnumerator access (push in one side, pop out the other)!
//[[17; 16; 15]; [14; 13; 12; 11; 10]; [9; 8; 7; 6; 5]; [4; 3; 2; 1; 0]]
let solution2 =
let split (s:seq<_>) n =
let e = s.GetEnumerator()
let rec each lstlst lst i =
if e.MoveNext() |> not then
lst::lstlst
elif i = n then
each (lst::lstlst) [e.Current] 1
else
each lstlst ((e.Current)::lst) (i+1)
each [] [] 0
split {0..17} 5
My third solution is based on the second solution except it "cheats" by taking a list as input instead of a seq, which enables the most elegant solution using pattern matching as Tomas points out is lacking with seq (which is why we were forced to use direct IEnumerator access).
//[[17; 16; 15]; [14; 13; 12; 11; 10]; [9; 8; 7; 6; 5]; [4; 3; 2; 1; 0]]
let solution3 =
let split inputList n =
let rec each inputList lstlst lst i =
match inputList with
| [] -> (lst::lstlst)
| cur::inputList ->
if i = n then
each inputList (lst::lstlst) [cur] 1
else
each inputList lstlst (cur::lst) (i+1)
each inputList [] [] 0
split [0..17] 5
If preserving the ordering of the elements is important, you can use List.rev for this purpose. For example, in solution2, change the last line of the split function to:
each [] [] 0 |> List.rev |> List.map List.rev
Out of the top of my head:
let rec split size list =
if List.length list < size then
[list]
else
(list |> Seq.take size |> Seq.toList) :: (list |> Seq.skip size |> Seq.toList |> split size)
Perhaps this simple pure implementation might be useful:
let splitAt n xs = (Seq.truncate n xs, if Seq.length xs < n then Seq.empty else Seq.skip n xs)
let rec chunk n xs =
if Seq.isEmpty xs then Seq.empty
else
let (ys,zs) = splitAt n xs
Seq.append (Seq.singleton ys) (chunk n zs)
For example:
> chunk 10 [1..100];;
val it : seq<seq<int>> =
seq
[seq [1; 2; 3; 4; ...]; seq [11; 12; 13; 14; ...];
seq [21; 22; 23; 24; ...]; seq [31; 32; 33; 34; ...]; ...]
> chunk 5 [1..12];;
val it : seq<seq<int>> =
seq [seq [1; 2; 3; 4; ...]; seq [6; 7; 8; 9; ...]; seq [11; 12]]
If in doubt, use fold.
let split n = let one, append, empty = Seq.singleton, Seq.append, Seq.empty
Seq.fold (fun (m, cur, acc) x ->
if m = n then (1, one x, append acc (one cur))
else (m+1, append cur (one x), acc))
(0, empty, empty)
>> fun (_, cur, acc) -> append acc (one cur)
This has the advantage of being fully functional, yet touch each element of the input sequence only once(*) (as opposed to the Seq.take + Seq.skip solutions proposed above).
(*) Assuming O(1) Seq.append. I should certainly hope so.
I found this to be easily the fastest:
let windowChunk n xs =
let range = [0 .. Seq.length xs]
Seq.windowed n xs |> Seq.zip range
|> Seq.filter (fun d -> (fst d) % n = 0)
|> Seq.map(fun x -> (snd x))
i.e. window the list, zip with a list of integers, remove all the overlapping elements, and then drop the integer portion of the tuple.
I think that the solution from Brian is probably the most reasonable simple option. A probelm with sequences is that they cannot be easily processed with the usual pattern matching (like functional lists). One option to avoid that would be to use LazyList from F# PowerPack.
Another option is to define a computation builder for working with IEnumerator type. I wrote something like that recently - you can get it here. Then you can write something like:
let splitEach chunkSize (s:seq<_>) =
Enumerator.toSeq (fun () ->
let en = s.GetEnumerator()
let rec loop n acc = iter {
let! item = en
match item with
| Some(item) when n = 1 ->
yield item::acc |> List.rev
yield! loop chunkSize []
| Some(item) ->
yield! loop (n - 1) (item::acc)
| None -> yield acc |> List.rev }
loop chunkSize [] )
This enables using some functional patterns for list processing - most notably, you can write this as a usual recursive function (similar to the one you would write for lists/lazy lists), but it is imperative under the cover (the let! constructo of iter takes the next element and modifies the enumerator).

F# Seq diff

given two sequences, how to get all the elements belonging to both the sequences or all the elements unique to one of them?
Example:
let a = [1..10]
let b = [3; 5; 7]
How do I compute 3 5 and 7 (all the elements common to both the list) and 1, 2, 4, 6, 8, 9, 10 (all the elements not in common)
Thanks
What you want to do is no more than the simple set operations of intersection and difference (or relative complement).
F# has the Set module to help us out here. This should do the job:
let a = [1 .. 10]
let b = [3; 5; 7]
let intersection = Set.intersect (Set.ofList a) (Set.ofList b)
let difference = (Set.ofList a) - (Set.ofList b)
You can then of course convert back the results into lists using Set.toList, if you wish.
As Mehrdad points out, this can be done alternatively using LINQ (or even the HashSet class in the BCL), but the approach here would seem to be most in the spirit of the F# language (certainly the nicest syntactically, and probably the most efficient too).
Slightly more compact:
let a = set [0;1;2;3]
let b = set [2;3;4;5]
let c = a - b
let d = b - a
let e = Set.intersect a b
let f = a + b
>
val c : Set<int> = seq [0; 1]
val d : Set<int> = seq [4; 5]
val e : Set<int> = seq [2; 3]
val f : Set<int> = seq [0; 1; 2; 3; ...]
Danny
Not very F#-y way I know of. You can always resort to .NET libraries. seq<T> is just IEnumerable<T>, nothing special:
let diff = System.Linq.Enumerable.Except(seq1, seq2); // seq1 - seq2
let intersect = System.Linq.Enumerable.Intersect(seq1, seq2);
let symdiff = System.Linq.Enumerable.Union(System.Linq.Enumerable.Except(seq1, seq2), System.Linq.Enumerable.Except(seq2, seq1));

F# Add an element to a sequence

a simple question I cannot find an answer to: how to add an element to a sequence? Eg I have a seq and a newElem XElement I'd like to append to it.
Thanks
Seq.append:
> let x = { 1 .. 5 };;
val x : seq<int>
> let y = Seq.append x [9];; // [9] is a single-element list literal
val y : seq<int>
> y |> Seq.toList;;
val it : int list = [1; 2; 3; 4; 5; 9]
You can also use
let newSeq = Seq.append oldSeq (Seq.singleton newElem)
Which is a slight modification of the first answer but appends sequences instead of a list to a sequence.
given the following code
let startSeq = seq {1..100}
let AppendTest = Seq.append startSeq [101] |> List.ofSeq
let AppendTest2 = Seq.append startSeq (Seq.singleton 101) |> List.ofSeq
let AppendTest3 = seq { yield! startSeq; yield 101 } |> List.ofSeq
looped 10000 executions the run times are
Elapsed 00:00:00.0001399
Elapsed 00:00:00.0000942
Elapsed 00:00:00.0000821
Take from that what you will.
There's also an imperative solution...
> let x = seq {1..5}
> let y = seq { yield! x; yield 9 } // Flatten the list,then append your element
> Seq.to_list y;;
val it : int list = [1; 2; 3; 4; 5; 9]
This may be better if the underlying problem is an imperative one, and it is most natural to use a yield statement in a loop.
let mySeq = seq { for i in 1..10 do yield i };;

Resources