I've got an array of strings, call it a, where each individual string represents a number. I also have a function f : int -> int -> int, which I want to use to "reduce a to a single number". I would like to write:
a |> Array.reduce (fun x y -> f (int32 x) (int32 y))
but this does not work, because the type of "reduce" forbids me from returning integers from f (since a is an array of strings)
Is there a functional way to make this work without having to return a
string from f or casting the string array to an int array beforehand?
using Array.reduce mapping first
If you don't want to adapt your f to handle strings, and you want to use Array.reduce then yeah I guess you should convert first (and to be honest: it seems easier than doing it manually with your wrapper-lambda) - so why not just use
a
|> Array.map int32
|> Array.reduce f
instead?
if you are concerned with the overhead of producing an intermediate Array you can always switch Array. with Seq. to to it lazily:
a |> Seq.map int32 |> Seq.reduce f
using Array.fold
aside from that you can always fold to your hearts desire:
a |> Array.fold (fun n s -> n + int32 s) 0
so you might call this more functional or not ;)
Related
I'm trying to read two integers which are going to be taken as input from the same line. My attempt so far:
let separator: char =
' '
Console.ReadLine().Split separator
|> Array.map Convert.ToInt32
But this returns a two-element array and I have to access the individual indices to access the integers. Ideally, what I would like is the following:
let (a, b) =
Console.ReadLine().Split separator
|> Array.map Convert.ToInt32
|> (some magic to convert the two element array to a tuple)
How can I do that?
I'm afraid there's no magic. You have to explicitly convert into a tuple
let a, b =
Console.ReadLine().Split separator
|> Array.map int
|> (fun arr -> arr.[0], arr.[1])
Edit: you can use reflection as #dbc suggested but that's slow and probably overkill for what you're doing.
I came across this syntax:
[10.; 11.; 12.]
|> List.map (fun a b -> a * b)
in what case does List.map have two parameters (fun a b)?
This is the output in Jupyter Lab:
That's a fun example, because it looks confusing and usually doesn't come up in practice, so it caught me off-guard initially.
In short, what happens is you're mapping a list of floats into a list of float -> float functions. It's easier to see if you rewrite it as something like this:
let results =
[10.; 11.; 12.]
|> List.map (fun a -> (fun b -> a * b))
You pass a float -> float -> float function as the mapper, and it gets partially applied to the element from the input list. The second argument b is not being applied though, so the output of the mapping is a function that takes a float and multiplies it by the partially applied element of the list, and the overall result is a list of float -> float functions.
You can then apply those functions to some value like this:
results
|> List.map (fun f -> f 2.)
Consider I have an array of options like [|Some 1;Some0;None;None;Some0|]
and i am going to get the indexes of elements with None value, in this case the correct answer would be [|2;3|].
My current idea is to change the array to a list and then go throw it using recursive function but in this case i will need mutable value to compute index, and i do not want to use mutable?
Is there any other solution
Here's another solution:
[|Some 1;Some 0;None;None;Some 0|]
|> Array.indexed
|> Array.filter (fun (i, x) -> x.IsNone)
|> Array.map fst
As an optimization last 2 lines can be replaced by a single |> Array.choose (function (i, None) -> Some i | _ -> None).
And here's another way using sequence expressions:
let x = [|Some 1;Some 0;None;None;Some 0|]
[|for i = 0 to x.Length-1 do
if x.[i].IsNone then yield i|]
I have an array like so:
let array = [|"A";"B";"C";"D"|]
I want to create an array based on the original array's value and the index like this:
[|"A",0;"B",1;"C",2;"D",4|]
If there a way to do this without resorting to a loop? I was thinking Seq.mapi or Seq.fold but I am not having much success with them....
Thanks in advance.
Function Array.mapi and Array.collect should do the trick:
array |> Array.mapi (fun i e -> (i, e)) |> Array.collect (fun (a, b) -> [|string a;b|])
Evaluation of this expression yields:
val it : string [] = [|"0"; "A"; "1"; "B"; "2"; "C"; "3"; "D"|]
However, I have converted integer to the string. Otherwise compiler can't infer type of the array.
If you need to have an array with elements of different type you can use Discriminated Union type.
Here is an example:
type ArrayElement =
| Int of int
| String of string
[|"A";"B";"C";"D"|] |> Array.mapi (fun i e -> (i, e)) |> Array.collect (fun (a, b) -> [|Int(a);String(b)|])
As Valera says, the answer lies in Array.mapi.
However I notice that your desired output isn't an array of differing types (strings and ints) as Valera suggests, but is an array of tuples of string*int.
In the light of this the answer is simpler:
let array = [|"A";"B";"C";"D"|]
array
|> Array.mapi (fun i s -> s, i)
(BTW I think your last index should be 3 not 4.)
The following code lists the set of keys found in a dictionary sequence (each dict is basically a row from a database). (I want to convert the keys to a set so I can compare 2 db tables)
for seqitem in tblseq do
let keyset = seqitem.Keys |> Set.ofSeq // works correctly
printfn ">>> List: %A; Item Type: %A" keyset
Rather than print the keyset however I want to return it from a function but am having a problem with type inference. Tried the following but it does not work;
What I want to do is return these values as either an array of list (rather than print them)
let get_keyset tblseq =
tblseq |> Seq.iter (fun x ->
x.Keys |> Set.ofSeq
)
What am I missing here?
Using Seq.map as ildjarn suggests is one option (you may want to add Array.ofSeq to the end to get array of sets as you say in your qurestion).
An alternative approach is to use array comprehension:
let get_keyset (tblseq:seq<System.Collections.Generic.Dictionary<_, _>>) =
[| for x in tblseq -> x.Keys |> Set.ofSeq |]
The notation [| .. |] says that you want to create an array of elements and the expression following -> specifies what should be produced as an element. The syntax is essentially just a nicer way for writing Seq.map (although it supports more features).
You can also use this syntax for creating sets (instead of calling Set.ofSeq). In this case, it doesn't make much sense, because Set.ofSeq is faster and sorhter, but sometimes it is quite neat option. It allows you to avoid type annotations, because you can get key of a dictionary using KeyValue pattern:
let get_keyset tblseq =
[| for x in tblseq ->
set [ for (KeyValue(k, v)) in x -> k ] |]
Use Seq.map rather than Seq.iter:
let get_keyset tblseq =
tblseq
|> Seq.map (fun (x:Dictionary<_,_>) -> x.Keys |> set)
|> Array.ofSeq