F# pattern filtering - f#

Can someone please give me advice on how to filter out a list of lists when it contains a certain number. For example, if the sub-lists contain 2 then I want the third value.
let p = [ [0;2;1]; [7;2;5]; [8;2; 10]; [44; 33; 9]]
//Filtered List: [1;5;10]
let q = p |> List.filter(fun((x,y):int List) (List.item 2 x) = 1, (List.item 3 y))
Above is my code so far. I know its wrong but can't seem to figure it out in code.

s952163's answer is correct, however, List.choose would be better.
p
|> List.choose (fun list ->
if List.contains 2 list then
Some list.[2]
else
None
)
With the solution above you only iterate through the list once.

I think you can just go by the way you described the problem:
p
|> List.filter (List.contains 2) //first filter out lists with 2 in it
|> List.map (fun x -> x.[2]) //get the third element, this is the same as List.item 2
//val it : int list = [1; 5; 10]

Related

how to calculate the max by column in a list of lists, with F#

With the following data (random strings):
let data =
[
["shi"; "cjwocij"; "cjwijo"]
["abs"; "djw"; "djwjdwojdow"]
["djido"; "dkwpkw"; "dpfkpeoep"]
]
I would like to calculate the max length by column.
I can transform the data into a list of lists of lengths:
data |> List.map (fun r -> r |> List.map (fun x -> x.Length))
index value
0 [ 3; 7; 6 ]
1 [ 3; 3; 11 ]
2 [ 5; 6; 9 ]
but ultimately I'd like to reduce it to:
[5; 7; 11]
by taking the max of each column
I thought I could do a fold and take the first row as a starting point, but it looks like it'll be quite convoluted.
For context: it's for a function that will take a grid and display it with proper spacing / formatting; all rows must have the same number of elements.
You need List.transpose. This turns rows into columns and vice versa.
data
|> List.map (fun r -> r |> List.map (fun x -> x.Length))
|> List.transpose
|> List.map List.max
val data : string list list =
[["shi"; "cjwocij"; "cjwijo"]; ["abs"; "djw"; "djwjdwojdow"];
["djido"; "dkwpkw"; "dpfkpeoep"]]
val it : int list = [5; 7; 11]
Here is a quick explicit version of transpose that might help (or hinder?) you grokking this:
let transpose lists =
[0 .. (List.length (List.head lists)) - 1]
|> List.map (fun col -> List.map (fun row -> List.item col row) lists )
This is the recursive version for completeness but I think the above is clearer if you are new to F#.
let rec transpose = function
| (_::_)::_ as l -> List.map List.head l :: transpose (List.map List.tail l)
| _ -> []
Update: I answered this in a comment but for others wondering over the second recursive solution:
The (_::_) ensures that a list is not empty. This is the same as (h::t) but we don't need to use h and t and so put the don't care place holder _ instead.
The second :: makes sure that the list of lists (listoflists) is non-empty or that (h::t)::c = (head of listoflists)::tail of listoflists so h::t is the first row, and c is all the other rows.
(_::_)::_ <=> (headRow0::tailRow0)::tailRows

How to copy elements in a list different number of times?

If I have a list consisting of elements [5;10;15], how can I get an output array in which the number of times element x from the input list is repeated x/5 times, or using any other integral expression to specify the number of repetitions?
So like for this list, the expected output should be [5; 10; 10; 15; 15; 15]
First, transform every element of the input list into a list with that many elements. To transform every element of a list, use List.map. To create a list with a given number of elements, use List.replicate:
let f lst =
lst
|> List.map (fun x -> List.replicate (x/5) x)
Let's test that:
> f [5; 10]
[ [5]; [10; 10] ]
And then, all that's left to do is concatenate all those lists into a big list using List.concat:
let f lst =
lst
|> List.map (fun x -> List.replicate (x/5) x)
|> List.concat
Or you can fuse map and concat together in collect:
let f lst =
lst
|> List.collect (fun x -> List.replicate (x/5) x)
You can define the following function returning a sequence using a sequence expression with nested for loops:
let repeatedSeq (s, itemCount) =
seq { for item in s do for i in 1..itemCount(item) -> item }
And then do:
let list = [5; 10; 15]
let repeatedList = repeatedSeq(list, fun i -> i/5) |> Seq.toList
Which results in [5; 10; 10; 15; 15; 15] as required. This approach avoids materializing any intermediate sequences as lists or arrays.
If you want your final result to be an array do |> Seq.toArray instead.
Demo fiddle here.

How do I do in F# what would be called compression in APL?

In APL one can use a bit vector to select out elements of another vector; this is called compression. For example 1 0 1/3 5 7 would yield 3 7.
Is there a accepted term for this in functional programming in general and F# in particular?
Here is my F# program:
let list1 = [|"Bob"; "Mary"; "Sue"|]
let list2 = [|1; 0; 1|]
[<EntryPoint>]
let main argv =
0 // return an integer exit code
What I would like to do is compute a new string[] which would be [|"Bob"; Sue"|]
How would one do this in F#?
Array.zip list1 list2 // [|("Bob",1); ("Mary",0); ("Sue",1)|]
|> Array.filter (fun (_,x) -> x = 1) // [|("Bob", 1); ("Sue", 1)|]
|> Array.map fst // [|"Bob"; "Sue"|]
The pipe operator |> does function application syntactically reversed, i.e., x |> f is equivalent to f x. As mentioned in another answer, replace Array with Seq to avoid the construction of intermediate arrays.
I expect you'll find many APL primitives missing from F#. For lists and sequences, many can be constructed by stringing together primitives from the Seq, Array, or List modules, like the above. For reference, here is an overview of the Seq module.
I think the easiest is to use an array sequence expression, something like this:
let compress bits values =
[|
for i = 0 to bits.Length - 1 do
if bits.[i] = 1 then
yield values.[i]
|]
If you only want to use combinators, this is what I would do:
Seq.zip bits values
|> Seq.choose (fun (bit, value) ->
if bit = 1 then Some value else None)
|> Array.ofSeq
I use Seq functions instead of Array in order to avoid building intermediary arrays, but it would be correct too.
One might say this is more idiomatic:
Seq.map2 (fun l1 l2 -> if l2 = 1 then Some(l1) else None) list1 list2
|> Seq.choose id
|> Seq.toArray
EDIT (for the pipe lovers)
(list1, list2)
||> Seq.map2 (fun l1 l2 -> if l2 = 1 then Some(l1) else None)
|> Seq.choose id
|> Seq.toArray
Søren Debois' solution is good but, as he pointed out, but we can do better. Let's define a function, based on Søren's code:
let compressArray vals idx =
Array.zip vals idx
|> Array.filter (fun (_, x) -> x = 1)
|> Array.map fst
compressArray ends up creating a new array in each of the 3 lines. This can take some time, if the input arrays are long (1.4 seconds for 10M values in my quick test).
We can save some time by working on sequences and creating an array at the end only:
let compressSeq vals idx =
Seq.zip vals idx
|> Seq.filter (fun (_, x) -> x = 1)
|> Seq.map fst
This function is generic and will work on arrays, lists, etc. To generate an array as output:
compressSeq sq idx |> Seq.toArray
The latter saves about 40% of computation time (0.8s in my test).
As ildjarn commented, the function argument to filter can be rewritten to snd >> (=) 1, although that causes a slight performance drop (< 10%), probably because of the extra function call that is generated.

Get lists from where each list will contain the elements from a x position from another collection of lists

basically having this:
[
[1;2;3];
[4;5;7];
[8;9;0];
]
I would like to get this (read vertically/ turn 90 degrees):
[
[1;4;8];
[2;5;9];
[3;7;0];
]
anybody knows an easy way of doing this in f# ?
I would do it by converting to arrays -
let arr = input |> List.map (List.toArray) |> List.toArray //a array of arrays
let out = Array2D.create size1 size2 (fun x y -> arr.[y].[x])
What you need is called matrix transposition.
PowerPack
The simplest way is using FSharp.PowerPack; Microsoft.FSharp.Math.Matrix module has Transpose method.
Simple algorithm
If you prefer your own solution, here's the one that demonstrates a good combination of short code and executing efficiency:
let rec transpose = function
| (_::_)::_ as M -> List.map List.head M :: transpose (List.map List.tail M)
| _ -> []
// use
[[1; 2; 3]; [4; 5; 6]; [7; 8; 9]]
|> transpose
|> printfn "%A"
In-place matrix transposition
Yet another approach is in-place matrix transposition. It has complexity of O(n), but requires mutable data.

Return value in F# - incomplete construct

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

Resources