How do you extract distinct elements from a list? - f#

I'm pretty new to f# and I'm having a hard time trying to extract a list of distinct values from a list:
let myList = [ 1; 2; 2; 3; 4; 3 ]
// desired list
[ 1; 2; 3; 4 ]
How do I do that? I see that seq has a distinct method, but not lists.

let myList = [ 1; 2; 2; 3; 4; 3 ]
let distinctList = myList |> Seq.distinct |> List.ofSeq
Result:
>
val myList : int list = [1; 2; 2; 3; 4; 3]
val distinctList : int list = [1; 2; 3; 4]
Next F# version (4.0) will have List.distinct function

Not sure if worse or better than Petr answer but you could also do :
let distinct xs = xs |> Set.ofList |> Set.toList
> distinct [ 1; 2; 2; 3; 4; 3 ];;
val it : int list = [1; 2; 3; 4]

Related

Remove a single element from an array

I've been at this for a few hours now, looking though every website and piece of documentation I could. I can't figure out how to remove one, and only one element (In this case, a string) from an array, keeping any duplicates in tact.
I did find a way, but, it's absolutely atrocious:
let remItem gs item =
if (chkItem gs item) then
let mutable fr = [| |] //temporary array
let mutable don = false //check if we found the element
for i in gs.inventory do
if not (i = item) && don then
fr <- (Array.append fr [|i|])
//add to the temp array until we find our item
elif i = item && don = false then don <- true
//we found it, skip just once so it doesn't get added
elif don then fr <- (Array.append fr [|i|])
//now just add everything else to the temp array
{ gs with inventory = fr }
else gs
I wrote this and I barely know how it works. Please tell me there's a better way to do this. I know the mutable variables aren't needed, but I've written a dozen equally horrendous-looking pure functions and concluded this is the best that I could do. I've tried a lot of the Array.* recursive functions already, I can't seem to make any of those comply with what I want either. I just want to know if it's even possible to do this neatly and purely in F#.
I think the easiest way to do this is to first look for the index (it's an array after all) and then just cut this out - this is (I think) a good compromise between performance and pureness - it's a pure operation but you don't get to much copy-operations:
let remove x (xs : 'a array) =
match Array.tryFindIndex ((=) x) xs with
| Some 0 -> xs.[1..]
| Some i -> Array.append xs.[..i-1] xs.[i+1..]
| None -> xs
please note that you have to take care of it beeing the first index because xs.[..(-1)] will throw an exception (while the other edge-case is ok):
> remove 0 [|1..10|];;
val it : int [] = [|1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
> remove 1 [|1..10|];;
val it : int [] = [|2; 3; 4; 5; 6; 7; 8; 9; 10|]
> remove 3 [|1..10|];;
val it : int [] = [|1; 2; 4; 5; 6; 7; 8; 9; 10|]
> remove 9 [|1..10|];;
val it : int [] = [|1; 2; 3; 4; 5; 6; 7; 8; 10|]
> remove 10 [|1..10|];;
val it : int [] = [|1; 2; 3; 4; 5; 6; 7; 8; 9|]
> remove 11 [|1..10|];;
val it : int [] = [|1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
if you need even more performance you could create an empty array and use a more imperative style to copy the parts:
let remove x (xs : 'a array) =
match Array.tryFindIndex ((=) x) xs with
| Some i ->
let res = Array.zeroCreate (xs.Length-1)
if i >= 1 then
System.Array.Copy(xs,0,res,0,i)
if i+1 < xs.Length then
System.Array.Copy(xs,i+1,res,i,xs.Length-i-1)
res
| None -> xs
Remove the first occurrence of a item from a list (taken from http://www.fssnip.net/1T):
let rec remove_first pred lst =
match lst with
| h::t when pred h -> t
| h::t -> h::remove_first pred t
| _ -> []
Usage:
let somelist = [('a',2);('f',7);('a',4);('h',10)]
let removed = somelist |> remove_first (fun (x,y) -> x='a')
// Result is:
// [('f',7);('a',4);('h',10)]
Fold should do the trick:
let remove x a =
Array.fold
(fun (s,found) t ->
if found || t <> x then Array.append s [|t|],found
else s,true) ([||],false) a |> fst
Example usage:
remove 2 [|1; 2; 3; 4; 2; 5|]
val it : int [] = [|1; 3; 4; 2; 5|]

F# finding only prime numbers

I'm recently new to F# so please bear with me. The problem i have is I'm trying to find only prime numbers.
I've write this code:
let isPrime n =
let rec check i =
i > n/2 || (n % i <> 0 && check (i + 1))
check 2;;
let listNums = List.filter isPrime >> List.length;;
let nums = [ 16; 17; 3; 4; 2; 5; 11; 6; 7; 18; 13; 14; ];;
let countPrimes (x:int) = x |> List.ofSeq |> listNums;;
trying to call
countPrimes nums;;
but this is failed with message:
The type 'int' is not compatible with the type 'seq<'a>'
any help would be appreciated
I found the solution
let isPrime n =
let rec check i =
i > n/2 || (n % i <> 0 && check (i + 1))
check 2;;
let listNums = List.filter isPrime >> List.length;;
let nums = [| 16; 17; 3; 4; 2; 5; 11; 6; 7; 18; 13; 14; |];;
let countPrimes (x:int[]) = x |> List.ofSeq |> listNums;;
countPrimes nums;;
Thanks all!
x |> List.ofSeq
seems to be the problem to me. You are passing an int into a function that requires a list. List.toSeq changes a list into a sequence. You want the function countPrimes to take a List of integers, not simply an integer. Although Carsten is right, listNums already takes a List of integers (edit: and computes the value you want provided isPrime is correct).
You do not need to countPrimes separately. Enough to remove and will work:
let isPrime n =
let rec check i =
i > n/2 || (n % i <> 0 && check (i + 1))
check 2
let nums = [ 16; 17; 3; 4; 2; 5; 11; 6; 7; 18; 13; 14; ]
let listPrime lst =
lst |> List.filter isPrime
nums |> listPrime |> printfn "%A"
Out:
[17; 3; 2; 5; 11; 7; 13]
Link:
https://dotnetfiddle.net/nVXwZ5

Slicing in a 2D Array in F# but similar to Matlab?

I was wondering if there is a way to use a list or an array of int as an index for slicing into a array to get a sub array in f#.
I know you can do the following
Arr2d.[*,1] or Arr2d.[1..5,1..2] etc...
But I was looking for something like in Matlab where you can write:
Arr2d([1;6;10],1) or Arr2d(1:10,[1;6;10])
Is it possible to do slicing like that in F#?
Thanks!
Here was my sample solution: (maybe not optimal but works)
let sampleMatrix = Array2D.init 10 5 (fun x y -> y)
val sampleMatrix : int [,] = [[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]
[0; 1; 2; 3; 4]]
let idxlist = [1;3;4]
let array2dColumnSlice (idxlist:list<int>) (data:'T[,]) =
let tmp = [|for i in idxlist -> data.[*,i]|]
Array2D.init tmp.[0].Length tmp.Length (fun x y -> tmp.[y].[x] )
let slice = array2dColumnSlice idxlist sampleMatrix
val slice : int [,] = [[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]
[1; 3; 4]]
As detailed here, there is no additional slicing notation beyond what you have already found.
For ranges only, it is possible, by wrapping Array2D with a sliceable type, or using the old PowerPack's Matrix type.
See the docs here:
http://msdn.microsoft.com/en-us/library/dd233214.aspx#sectionToggle6
You can use this slicing syntax for types that implement the element
access operators and overloaded GetSlice methods. For example, the
following code creates a Matrix type that wraps the F# 2D array,
implements an Item property to provide support for array indexing, and
implements three versions of GetSlice. If you can use this code as a
template for your matrix types, you can use all the slicing operations
that this section describes.

F# List.Map using a random number

I want to create a list of 20 random numbers. I wrote this:
let numberList = [ 1 .. 20 ]
let randoms =
numberList
|> List.map (fun (x) -> System.Random().Next(0,9))
And I got this:
val numberList : int list =
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19; 20]
val randoms : int list =
[7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7; 7]
Which makes sense. The problem is that I want to pass in a random number each time the function is evaluated like this:
let numberList = [ 1 .. 20 ]
let randoms =
numberList
|> List.map (fun (Random().Next(0,9)) -> x)
but I am getting a "The pattern discriminator 'Random' is not defined" exception.
Am i approaching this problem the wrong way?
Thanks in advance
In your original version, you create a new Random object at each iteration. As this is seeded with the current time, you always create the same sequence.
You need to create the object outside map like so
let RNG = new System.Random()
numberlist |> List.map (fun x -> RNG.Next(0,9))
Although a more elegant solution would be
let RNG = new System.Random()
let randoms = List.init 20 (fun _ -> RNG.Next(0,9))
Your second version fails because you are trying to treat Random as a pattern which makes no sense in this situation.

How to generate a multiplication table sequence?

I want to generate a sequence like a multiplication table. So for a start of 1 and a stop of 10 I am looking for a sequence like
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 1*1 - 1*10
2, 4, 6, 8, 10, 12, 14, 16, 18, 20, // 2*1 - 2*10
3, 6, 9, 12, ... // 3*1 - 3*10
Here is my lame start at it, however I can't seem to figure out how to cleanly increment j when the stop is reached, or how to reset i back to the start.
let multable (start,stop) =
(start,start)
|> Seq.unfold(
fun (i,j) ->
Some(i*j, (i+1, j)))
let its = multable(1, 1)
let first10 = Seq.take 10 its
printf "%A" (Seq.to_list first10)
Which of course gives me 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
I can't really think of many cases where I'd prefer Seq.unfold over an equivalent list comprehension:
> let multiplication n m = [for a in 1 .. n -> [for b in 1 .. m -> a * b ] ];;
val multiplication : int -> int -> int list list
> multiplication 5 5;;
val it : int list list =
[[1; 2; 3; 4; 5]; [2; 4; 6; 8; 10]; [3; 6; 9; 12; 15]; [4; 8; 12; 16; 20];
[5; 10; 15; 20; 25]]
Occasionally the Array.init methods are useful too:
> let multiplication n m = Array2D.init n m (fun n m -> n * m);;
val multiplication : int -> int -> int [,]
> multiplication 5 5;;
val it : int [,] = [[0; 0; 0; 0; 0]
[0; 1; 2; 3; 4]
[0; 2; 4; 6; 8]
[0; 3; 6; 9; 12]
[0; 4; 8; 12; 16]]
Use a sequence expression:
let multable start stop = seq{
for a = start to stop do
for b = start to stop do
yield a*b
}
Output:
> multable 1 3 |> Seq.to_list;;
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]
It's weird to represent a fundamentally 2d structure in this fashion. Why not a sequence of sequences:
let multable2 start stop = seq {
for a = start to stop do yield seq {
for b = start to stop do
yield a*b
}
}
Output:
val multable2 : int -> int -> seq<seq<int>>
> multable2 1 3 |> Seq.to_list;;
val it : seq<int> list = [seq [1; 2; 3]; seq [2; 4; 6]; seq [3; 6; 9]]
If you want to be "clever" and avoid multiplication:
let multable4 start stop = seq {
for a = start to stop do yield seq {
let s = ref 0 in
for b = start to stop do
s:=!s+a
yield !s
}
}
I don't actually see any nice prepackaged "sequence from a to b" outside of comprehensions/sequence expressions, although there's obviously [a..b] (list) and [|a..b|] (array) which you can project through Seq.unfold, Seq.map, etc. to make a Seq.
let Table r c =
[for row in 1..r do
yield [for col in 1..c do
yield row * col]]
printfn "%A" (Table 5 4)
// [[1; 2; 3; 4]; [2; 4; 6; 8]; [3; 6; 9; 12]; [4; 8; 12; 16]; [5; 10; 15; 20]]
Here's another way to use sequences:
let rec fromXToY x y =
seq {
if x <= y
then yield x; yield! fromXToY (x + 1) y;
else ()
}
let scaledSequence factor items =
Seq.map (fun x -> factor * x) items
let mulTable x y =
let sequenceOfIntegersMultipliedByValue = (fun n -> scaledSequence n (fromXToY x y))
let seqOfSeqOfValues = Seq.map sequenceOfIntegersMultipliedByValue (fromXToY x y)
// Convert the sequence of sequences to a simple sequence of values
Seq.fold Seq.append Seq.empty seqOfSeqOfValues

Resources