I have string "DBCA" and want sort it in F#
let sortedString str =
...
printfn "%A" <| sortedString "DBCA" // "ABCD"
Code sample on C#
String
.Concat(
_str
.OrderBy(ch => ch)
);
open System
let sortedString (str : string) = str |> Seq.sort |> String.Concat
Solution with LINQ
open System
open System.Linq
let orderBy f xs = Enumerable.OrderBy(xs, new Func<_,_>(f))
let sortedString (str:string) =
str
|> List.ofSeq
|> orderBy (fun ch -> ch)
|> String.Concat
I had this solution, but above answer is better
Related
module CounterApp
open System
open System.Windows
open System.Windows.Controls
open System.Windows.Media
open System.Reactive.Linq
open System.Reactive.Disposables
open FSharp.Control.Reactive
/// Subscribers
let do' f c = f c; Disposable.Empty
let prop s v c = Observable.subscribe (s c) v
let event s f c = (s c : IEvent<_,_>).Subscribe(fun v -> f c v)
let children clear add set (v1 : IObservable<IObservable<IObservable<_>>>) c = // Note: The previous versions of this have bugs.
let v2_disp = new SerialDisposable()
new CompositeDisposable(
v1.Subscribe(fun v2 ->
clear c
v2_disp.Disposable <-
let v3_disp = new CompositeDisposable()
let mutable i = 0
new CompositeDisposable(
v2.Subscribe (fun v3 ->
let i' = i
v3_disp.Add <| v3.Subscribe (fun v -> if i' < i then set c i' v else i <- add c v + 1)
),
v3_disp
)
),
v2_disp
)
:> IDisposable
let ui_element_collection v1 c = children (fun (c : UIElementCollection) -> c.Clear()) (fun c -> c.Add) (fun c i v -> c.RemoveAt i; c.Insert(i,v)) v1 c
/// Transformers
let control'<'a when 'a :> UIElement> (c : unit -> 'a) l =
Observable.Create (fun (sub : IObserver<_>) ->
let c = c()
let d = new CompositeDisposable()
List.iter (fun x -> d.Add(x c)) l
sub.OnNext(c)
d :> IDisposable
)
let control c l = control' c l :?> IObservable<UIElement>
let stack_panel' props childs = control StackPanel (List.append props [fun c -> ui_element_collection childs c.Children])
let stack_panel props childs = stack_panel' props (Observable.ofSeq childs |> Observable.single)
let window props content = control' Window (List.append props [prop (fun t v -> t.Content <- v) content])
/// The example
type Model = {
Count : int
Step : int
TimerOn : bool
}
type Msg =
| Increment
| Decrement
| Reset
| SetStep of int
| TimerToggled of bool
| TimedTick
let init = { Count = 0; Step = 1; TimerOn=false }
let pump = Subject.broadcast
let dispatch msg = pump.OnNext msg
let update =
pump
|> Observable.scanInit init (fun model msg ->
match msg with
| Increment -> { model with Count = model.Count + model.Step }
| Decrement -> { model with Count = model.Count - model.Step }
| Reset -> init
| SetStep n -> { model with Step = n }
| TimerToggled on -> { model with TimerOn = on }
| TimedTick -> if model.TimerOn then { model with Count = model.Count + model.Step } else model
)
|> Observable.startWith [init]
let timerCmd() =
update
|> Observable.map (fun x -> x.TimerOn)
|> Observable.distinctUntilChanged
|> Observable.combineLatest (Observable.interval(TimeSpan.FromSeconds(1.0)))
|> Observable.subscribe (fun (_,timerOn) ->
if timerOn then Application.Current.Dispatcher.Invoke(fun () -> dispatch TimedTick)
)
let view =
window [ do' (fun t -> t.Title <- "Counter App")]
<| control Border [
do' (fun b -> b.Padding <- Thickness 30.0; b.BorderBrush <- Brushes.Black; b.Background <- Brushes.AliceBlue)
prop (fun b v -> b.Child <- v) <|
stack_panel [ do' (fun p -> p.VerticalAlignment <- VerticalAlignment.Center)] [
control Label [
do' (fun l -> l.HorizontalAlignment <- HorizontalAlignment.Center; l.HorizontalContentAlignment <- HorizontalAlignment.Center; l.Width <- 50.0)
prop (fun l v -> l.Content <- v) (update |> Observable.map (fun model -> sprintf "%d" model.Count))
]
control Button [
do' (fun b -> b.Content <- "Increment"; b.HorizontalAlignment <- HorizontalAlignment.Center)
event (fun b -> b.Click) (fun b arg -> dispatch Increment)
]
control Button [
do' (fun b -> b.Content <- "Decrement"; b.HorizontalAlignment <- HorizontalAlignment.Center)
event (fun b -> b.Click) (fun b arg -> dispatch Decrement)
]
control Border [
do' (fun b -> b.Padding <- Thickness 20.0)
prop (fun b v -> b.Child <- v) <|
stack_panel [do' (fun p -> p.Orientation <- Orientation.Horizontal; p.HorizontalAlignment <- HorizontalAlignment.Center)] [
control Label [do' (fun l -> l.Content <- "Timer")]
control CheckBox [
prop (fun c v -> c.IsChecked <- Nullable(v)) (update |> Observable.map (fun model -> model.TimerOn))
event (fun c -> c.Checked) (fun c v -> dispatch (TimerToggled true))
event (fun c -> c.Unchecked) (fun c v -> dispatch (TimerToggled false))
]
]
]
control Slider [
do' (fun s -> s.Minimum <- 0.0; s.Maximum <- 10.0; s.IsSnapToTickEnabled <- true)
prop (fun s v -> s.Value <- v) (update |> Observable.map (fun model -> model.Step |> float))
event (fun s -> s.ValueChanged) (fun c v -> dispatch (SetStep (int v.NewValue)))
]
control Label [
do' (fun l -> l.HorizontalAlignment <- HorizontalAlignment.Center)
prop (fun l v -> l.Content <- v) (update |> Observable.map (fun model -> sprintf "Step size: %d" model.Step))
]
control Button [
do' (fun b -> b.HorizontalAlignment <- HorizontalAlignment.Center; b.Content <- "Reset")
prop (fun b v -> b.IsEnabled <- v) (update |> Observable.map (fun model -> model <> init))
event (fun b -> b.Click) (fun b v -> dispatch Reset)
]
]
]
[<STAThread>]
[<EntryPoint>]
let main _ =
let a = Application()
use __ = view.Subscribe (fun w -> a.MainWindow <- w; w.Show())
use __ = timerCmd()
a.Run()
I am translating the Fabulous counter example to reactive extensions. The above works, but I am not completely satisfied with how the command aspect came out.
let timerCmd() =
update
|> Observable.map (fun x -> x.TimerOn)
|> Observable.distinctUntilChanged
|> Observable.combineLatest (Observable.interval(TimeSpan.FromSeconds(1.0)))
|> Observable.subscribe (fun (_,timerOn) ->
if timerOn then Application.Current.Dispatcher.Invoke(fun () -> dispatch TimedTick)
)
This is how the timer command is defined as a function.
use __ = timerCmd()
I subscribe to it in the main function.
This is not quite expressing what I want.
For one, I do not want this to be a separate subscription in main. I do not want the interval observable to be turned on all the time in the background, only sending messages when allowed.
I want timerCmd to switch on automatically, subscribe to the interval and dispatch TimedTick messages - and switch off and unsubscribe based on the state of x.TimerOn. What would the best way to do this be? Is there a better way to design all of this?
Yes, it's possible to shunt an interval timer in and out of the stream.
We can project onto an observable of either empty notifications or an interval, and then switch to the newest emitted observable.
let model = { Count = 0; Step = 0; TimerOn = false }
let update = Subject.behavior model
update
|> Observable.distinctUntilChangedKey (fun x -> x.TimerOn)
|> Observable.map (fun x ->
if x.TimerOn then
Observable.interval(TimeSpan.FromSeconds(1.0))
else
Observable.empty
)
|> Observable.switch
|> Observable.subscribe (fun i -> printfn "Tick %d" i)
|> ignore
while true do
printfn "Start (y)?"
let switch = Console.ReadLine()
update
|> Subject.onNext( { model with TimerOn = switch = "y" })
|> ignore
Output
Start (y)?
y
Start (y)?
Tick 0
Tick 1
Tick 2
Tick 3
n
Start (y)?
y
Start (y)?
Tick 0
Tick 1
As you can see the timer does restart when you want it to.
I have a data contract (WCF) with a field defined as:
[<DataContract(Namespace = _Namespace.ws)>]
type CommitRequest =
{
// Excluded for brevity
...
[<field: DataMember(Name="ExcludeList", IsRequired=false) >]
ExcludeList : int array option
}
I want to from the entries in the ExcludeList, create a comma separated string (to reduce the number of network hops to the database to update the status). I have tried the following 2 approaches, neither of which create the desired string, both are empty:
// Logic to determine if we need to execute this block works correctly
try
// Use F# concat
let strList = request.ExcludeList.Value |> Array.map string
let idString = String.concat ",", strList
// Next try using .NET Join
let idList = String.Join ((",", (request.ExcludeList.Value.Select (fun f -> f)).Distinct).ToString ())
with | ex ->
...
Both compile and execute but neither give me anything in the string. Would greatly appreciate someone pointing out what I am doing wrong here.
let intoArray : int array option = Some [| 1; 23; 16 |]
let strList = intoArray.Value |> Array.map string
let idString = String.concat "," strList // don't need comma between params
// Next try using .NET Join
let idList = System.String.Join (",", strList) // that also works
Output:
>
val intoArray : int array option = Some [|1; 23; 16|]
val strList : string [] = [|"1"; "23"; "16"|]
val idString : string = "1,23,16"
val idList : string = "1,23,16"
I am new to programming and F# is my first language.
Here is part of my code:
let splitArrayIntoGroups (inputArray: string[]) (groupSize: int) =
let groups = new LinkedList<string[]>()
let rec splitRecursively currentStartIndex currentEndIndex =
groups.AddLast(inputArray.[currentStartIndex..currentEndIndex]) |> ignore
let newEndIndex = Math.Min((inputArray.Length - 1), (currentEndIndex + groupSize))
if newEndIndex <> currentEndIndex then
splitRecursively (currentStartIndex + groupSize) newEndIndex
splitRecursively 0 (groupSize - 1)
groups
I want this function to be able to accept arrays of any type (including types that I define myself) as input. What changes should I make?
This was already answered but here you have an implementation not using a linked list but just an array of lists
let rec split<'T> (input: 'T array) size =
let rec loopOn (tail : 'T array) grouped =
let lastIndex = Array.length tail - 1
let endindx = min (size - 1) lastIndex
let arrWrapper = (fun e -> [|e|])
let newGroup = tail.[0..endindx]
|> List.ofArray
|> arrWrapper
|> Array.append grouped
match tail with
| [||] -> newGroup
|> Array.filter (fun e -> List.length e > 0)
| _ -> loopOn tail.[endindx + 1..] newGroup
let initialState = [|List.empty<'T>|]
loopOn input initialState
Because this is generic implementation you can call it with different types
type Custom = {Value : int}
let r = split<int> [|1..1000|] 10
let r2 = split<float> [|1.0..1000.0|] 10
let r3 = split<Custom> [|for i in 1..1000 ->
{Value = i}|] 10
replace string[] with _[] in the function signature.
I need to write a running number - at the beginning of existing files. All I have been able to do so far is to write to the end of each file. Any help please?
How about (warning! untested code):
open System.IO
File.ReadAllText("c:\\old.txt")
|> fun s -> let r = new StreamReader(s)
let data = r.ReadToEnd
r.Close()
s.Close()
data
let writeStringToFile d =
(File.OpenWrite("c:\\new.txt"), d)
|> fun ((s : FileStream), (d : string)) -> let r = new StreamWriter(s)
r.WriteLine("new data")
r.Write(d)
r.Close()
s.Close()
getStringFromFile()
|> writeStringToFile
EDIT:
Much better solution:
File.WriteAllText("c:\\new.txt", "new Text" + File.ReadAllText("c:\\old.txt"))
I use F# once every few months or so and in between it seems I forget everything, so I hope you'll excuse my ignorance. My code below is pulling data from Yahoo. It's a good example that represents what I need to do. The first row returned has the column headings. I need to take the data (the tail of the list) and insert it into the database. What's the best way to generate an insert statement based on the column headings returned (the column headings match the database column names)?
In the example below dataWithHeaders.[0] will contain "Date,Open,High,Low,Close,Volume,Adj Close." Should I just take that string and put brackets around the headings to create the insert? Then in insertData add the value as a parameter? Is there a more elegant solution?
let url = System.String.Format("http://ichart.finance.yahoo.com/table.csv?s={0}&g=d&ignore=.csv", "FB")
let splitLineIntoArray (line : string) =
line.Split(",".ToCharArray())
let insertData (data : string[]) =
// insert data
()
let client = new WebClient()
let dataWithHeaders =
client.DownloadString(url).Split(Environment.NewLine.ToCharArray())
let data =
dataWithHeaders
|> Array.toList
|> List.tail
|> List.map(splitLineIntoArray)
|> List.iter insertData
If you're loading the data into SQL Server you can use this excellent CSV reader (free) and the SqlBulkCopy class. It's simple and efficient.
let loadStockPrices ticker =
use client = new WebClient()
let url = sprintf "http://ichart.finance.yahoo.com/table.csv?s=%s&g=d&ignore=.csv" ticker
use stringReader = new StringReader(client.DownloadString(url))
use csvReader = new CsvReader(stringReader, hasHeaders=true)
use con = new SqlConnection("<connection_string>")
con.Open()
use bulkCopy = new SqlBulkCopy(con, DestinationTableName="<destination_table>")
bulkCopy.WriteToServer(csvReader)
The destination table should have the same columns as the incoming data (OHLC, etc).
EDIT: Type Providers might be a good way to go, but SqlBulkCopy is def. known for its simplicity.
Type Provider Code for Insert: http://msdn.microsoft.com/en-us/library/hh361033(v=vs.110).aspx#BKMK_UpdateDB
type dbSchema = SqlDataConnection<"Data Source=MYSERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;">
let db = dbSchema.GetDataContext()
// Enable the logging of database activity to the console.
db.DataContext.Log <- System.Console.Out
let newRecord = new dbSchema.ServiceTypes.Table1(Id = 100,
TestData1 = 35,
TestData2 = 2.0,
Name = "Testing123")
let newValues =
[ for i in [1 .. 10] ->
new dbSchema.ServiceTypes.Table3(Id = 700 + i,
Name = "Testing" + i.ToString(),
Data = i) ]
// Insert the new data into the database.
db.Table1.InsertOnSubmit(newRecord)
db.Table3.InsertAllOnSubmit(newValues)
try
db.DataContext.SubmitChanges()
printfn "Successfully inserted new rows."
with
| exn -> printfn "Exception:\n%s" exn.Message
I did something similar. Actually this code I wrote while watching Luca Bolognese give a presentation on F#. This actually will scrape yahoo's feed and return the standard dev. and variance on stock prices.
Full project here: https://github.com/djohnsonm/Stock-Ticker-App
open System.Net
open System.IO
let internal loadPrices ticker = async {
let url = #"http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&d=6&e=22&f=2011&g=d&a=2&b=13&c=1986&ignore=.csv"
let req = WebRequest.Create(url)
let resp = req.GetResponse()
let stream = resp.GetResponseStream()
let reader = new StreamReader(stream)
let csv = reader.ReadToEnd()
let prices =
csv.Split([|'\n'|])
|> Seq.skip 1
|> Seq.map (fun line -> line.Split([|','|]))
|> Seq.filter(fun values -> values |> Seq.length = 7)
|> Seq.map(fun values ->
System.DateTime.Parse(values.[0]),
float values.[6])
return prices}
type StockAnalyzer (lprices, days) =
let prices =
lprices
|> Seq.map snd
|> Seq.take days
static member GetAnalyzers (tickers, days) =
tickers
|> Seq.map loadPrices
|> Async.Parallel
|> Async.RunSynchronously
|> Seq.map (fun prices -> new StockAnalyzer(prices, days))
member s.Return =
let lastPrice = prices |> Seq.nth 0
let startPrice = prices |> Seq.nth(days-1)
lastPrice / startPrice - 1.
member s.StdDev =
let logRets =
prices
|> Seq.pairwise
|> Seq.map (fun (x,y) -> log(x/y))
let mean = logRets |> Seq.average
let sqr x = x * x
let var = logRets |> Seq.averageBy (fun r -> sqr (r-mean))
sqrt var