I would like to create create a graph of an array on F sharp as follows:
let compperformance= Array.zip firstarray secondarray |> Array.map (fun (a,b)
-> (b-a))
Chart.Line(compperformance, Title="dy").WithXAxis(Title="year", Min=1.0, Max=39.0)
.WithYAxis(Title="Cumulative SSE difference")
How can I change the x-axis to year (min=1960.0 to max=2000.0)? When I define min and max as such, the graph disappears. Let me know.
You can pass a sequence of key value pairs to Chart.Line:
let compperformance=
Array.zip firstarray secondarray |> Array.map (fun (a,b) -> (b-a))
let dataWithYears =
Array.zip [| 1960 .. 2000 |] compperformance
Chart.Line(dataWithYears, Title="dy")
.WithXAxis(Title="year", Min=1.0, Max=39.0)
.WithYAxis(Title="Cumulative SSE difference")
This assumes that there is exactly 41 values in compperformance, which might not quite work - you may need to do this a bit differently - but it shows the idea - just produce an array containing year, value tuples.
Related
I am looking for a type similar to sequences in F# where indices could be big integers, rather that being restricted to int. Does there exist anything like this?
By "big integer indices" I mean a type which allows for something equivalent to that:
let s = Seq.initInfinite (fun i -> i + 10I)
The following will generate an infinite series of bigints:
let s = Seq.initInfinite (fun i -> bigint i + 10I)
What i suspect you actually want though is a Map<'Key, 'Value>.
This lets you efficiently use a bigint as an index to look up whatever value it is you care about:
let map =
seq {
1I, "one"
2I, "two"
3I, "three"
}
|> Map.ofSeq
// val map : Map<System.Numerics.BigInteger,string> =
// map [(1, "one"); (2, "two"); (3, "three")]
map.TryFind 1I |> (printfn "%A") // Some "one"
map.TryFind 4I |> (printfn "%A") // None
The equivalent of initInfinite for BigIntegers would be
let inf = Seq.unfold (fun i -> let n = i + bigint.One in Some(n, n)) bigint.Zero
let biggerThanAnInt = inf |> Seq.skip (Int32.MaxValue) |> Seq.head // 2147483648
which takes ~2 min to run on my machine.
However, I doubt this is of any practical use :-) That is unless you start at some known value > Int32.MaxValue and stop reasonably soon (generating less than Int32.MaxValue items), which then could be solved by offsetting the BigInt indexes into the Int32 domain.
Theoretically you could amend the Seq module with functions working with BigIntegers to skip / window / ... an amount of items > Int32.MaxValue (e.g. by repeatedly performing the corresponding Int32 variant)
Since you want to index into a sequence, I assume you want a version of Seq.item that takes a BigInteger as index. There's nothing like that built into F#, but it's easy to define your own:
open System.Numerics
module Seq =
let itemI (index : BigInteger) source =
source |> Seq.item (int index)
Note that no new type is needed unless you're planning to create sequences that are longer than 2,147,483,647 items, which would probably not be practical anyway.
Usage:
let items = [| "moo"; "baa"; "oink" |]
items
|> Seq.itemI 2I
|> printfn "%A" // output: "oink"
I have an array with multiple lists inside and want to write the values to an CSV
unfortunately I cannot figure out how to write the Array.mapi.
Any ideas?
let temp = [|title;body;ordinariePris;extraPris;inkopPris;images;allValues|]
let lines2 =
temp
|> Array.mapi (fun idx (t,b,op,ep,ip,i,av) ->
sprintf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" title body ordinariePris extraPris inkopPris images allValues
)
let header = "title\tbody\tordinariePris\textraPris\tinkopPris\tallValues"
System.IO.File.WriteAllLines("test.csv",
Array.append [| header|]lines2, Encoding.UTF8)
thanks in advance
The problem with your code is that mapi indexes over the elements of temp, which means that you're only getting one column at a time. You want to retrieve one row at a time.
The following instead transposes your list of lists, so that indexing does what you want. It's also a little more generic-- you don't actually need to know the number of columns ahead of time. It does, however, assume that every column has the same number of elements in it.
let col1 = ["a"; "b"; "c"]
let col2 = ["1"; "2"; "3"]
let col3 = ["x"; "y"; "z"]
let cols = [col1; col2; col3]
let transpose(xs: string list list) : string list list =
[0 .. xs.[0].Length - 1] |> List.map (fun i ->
xs |> List.rev |> List.fold (fun acc col -> col.[i] :: acc) []
)
let stringify_rows(xs: string list list) : string list =
xs |> List.map (fun row -> System.String.Join(",", row))
System.IO.File.WriteAllLines("test.csv", cols |> transpose |> stringify_rows)
Note that this approach does not use an array of lists, since there was no obvious reason that you had to use an array. WriteAllLines will happily accept any IEnumerable.
If you do a lot of CSV writing, I recommend using a library like CsvHelper, since correctly handling when to quote or escape cell contents can be tricky.
I am new to programming, and this is my first time working with a typed, functional, and .NET language, so pardon me if my question is silly/trivial.
I have a list of tuples, and I would like to store the first item (which is a string) of each tuple as a value in the hashtable, and the second item (which is a byte array) of each tuple as a key. How may I go about doing so?
Here is my code:
let readAllBytes (tupleOfFileLengthsAndFiles) =
let hashtable = new Hashtable()
tupleOfFileLengthsAndFiles
|> snd
|> List.map (fun eachFile -> (eachFile, File.ReadAllBytes eachFile))
|> hashtable.Add(snd eachTuple, fst eachTuple)
However, the last line is underscored in red. How can I improve it? Thanks in advance for your help.
The easies way is to use dict
It will convert a sequence of tuples in a Dictionary which is a string type Hashtable.
> dict [(1,"one"); (2,"two"); ] ;;
val it : System.Collections.Generic.IDictionary<int,string> =
seq [[1, one] {Key = 1;
Value = "one";}; [2, two] {Key = 2;
Value = "two";}]
If you are really interested in a Hashtable you can use this simple function:
let convert x =
let d = Hashtable()
x |> Seq.iter d.Add
d
So, I'm not sure what do you want to do with this, it seems you're also interested in reading the file in the middle of the conversion. May be something like this:
let readAllBytes (tupleOfFileLengthsAndFiles:seq<'a*'b>) =
tupleOfFileLengthsAndFiles
|> Seq.map (fun (x, y) -> x, File.ReadAllBytes y)
|> convert
I have the following demand: getting the array of tuples from the first array according to the elements’ appearance in the second array:
let totals = [| ("old1", "new1"); ("old2", "new2"); ("old3", "new3"); ("old4", "new4") |]
let changes = [| "new1"; "new4" |]
I want to have this:
let updates = [| ("old1", "new1"); ("old4", "new4") |]
If the both arrays totals and changes have the same length, then I think it is easy:
let updates = Array.zip changes totals
|> Array.choose(fun (a, B) -> if a = fst(B) then Some (B) else None)
Unfortunately, totals and changes have different number of elements; therefore, I can not find an easy way to get the elements I need.
The solution posted by pad is correct and will work fine for small number of elements in changes. However, it iterates over the array changes for every element in total, so it may be inefficient for large arrays.
As an alternative, you can turn changes into an F# set type which allows more efficient membership test:
// Create set containing 'changes'
let changesSet = Set.ofArray changes
// Filter totals where the second element is in 'changesSet'
totals |> Array.filter (fun (_, v) -> changesSet.Contains(v))
// Same thing using function composition
totals |> Array.filter (snd >> changesSet.Contains)
You should select pairs in totals which have second elements occur in changes:
let updates =
totals
|> Array.filter (fun (_, x) -> changes |> Array.exists (fun y -> y = x))
For an F# array, is there an easy way to return sorting indices along with the sorted array?
Like the sort() function from Matlab?
Background: I came from matlab/R, where manipulating array on indices are essential.
I'd like to reproduce some index functions and trying to be able to pass indices array around as a variable in various functions. for this sort() function, one usage would be sorting several aligned arrays together based on any one of them.
Maybe there are better ways to do this?
Use Array.sort in combination with Array.mapi.
let arr = [| 14;3;11;2 |]
let sortedWithIndex = arr |> Array.mapi (fun x t -> (t,x)) |> Array.sort
printfn "%A" sortedWithIndex
output
[|(2, 3); (3, 1); (11, 2); (14, 0)|]
let sortWithIndex list =
list
|> List.mapi (fun index x -> (x, index))
|> List.sort
(Depending on the version of F#, List.sort might require a comparison function like `compare ).