2016-12-01 130 views
1

我目前正在努力學習F#,並且我正在使用codingame作爲編程測驗的來源。什麼是從標準輸入讀取的最佳方式?

大部分quizess涉及從標準輸入讀取一些值,就像stdin中的前十個值是整數,接下來的五個值將是字符串。

目前,我使用這個函數來讀取數據,但它感覺非常「un-f#」。

let N = 5 
let Reader i = 
    Console.In.ReadLine() 

let words = [0..N-1] |> Seq.map Reader 
+1

什麼是你的問題? –

+0

@MarkSeemann什麼是更好的方式從標準輸入讀取N次? –

+1

我通常會讓'words = [for _ in 1 ... N - > Console.ReadLine()]'或者其他的(取決於遊戲)。但是我同意@MarkSeemann:不清楚問題是什麼。 –

回答

4

如果我有閱讀給定類型的給定的數字,我就喜歡寫東西

open System 

let read parser = 
    Seq.initInfinite (fun _ -> Console.ReadLine()) 
    |> Seq.choose (parser >> function true, v -> Some v | _ -> None) 

然後其可用於

let ints = read Int32.TryParse 
let ``ten floats`` = read Double.TryParse |> Seq.take 10 

注意,如果seq使用多次,ReadLine()再次調用:

let anInt = ints |> Seq.take 1 
printfn "%A" anInt 
printfn "%A" anInt // need to input an int again 

其可以通過使用例如被處理ListSeq.cache

對於字符串,它永遠不會失敗,使用

let strings = read (fun s -> true, s) 

,如果你有一個最小長度要求:

let potentialPasswords = read (fun s -> s.Length > 10, s) 
+0

我真的很喜歡你在這裏展示的作品,謝謝! –

7

從註釋中,很明顯,你最喜歡的「F#-native」(我們稱之爲「地道F#」)從控制檯讀取的方式。

你有什麼是地道的就夠了,除了功能,按照慣例,通常用小寫字母開頭:

let reader i = Console.ReadLine() 

另外,因爲你不使用參數,你不必給它一個名字:

let reader _ = Console.ReadLine() 

如果功能足夠小,可以在線寫,匿名:

let words = [0..N-1] |> Seq.map (fun _ -> Console.ReadLine()) 

另外,由於您實際上並未使用索引,因此您可以將列表聲明爲1..N而不是0..N-1。看起來有點乾淨。

最後,F#提供,你可以用它來實現更好的可讀性非常方便列表解析:

let N = 5 
let words = [for _ in 1..N -> Console.ReadLine()] 
+0

非常好的答案謝謝你 - 我採取了另一個答案,因爲我喜歡直接解析數據的能力,但我更喜歡你的解釋 - 雖然是通話。 –

+1

請注意F#中特殊的stdin值,它可以用作快捷方式:'stdin.ReadLine()'。還有一個'stdout.WriteLine()'。關於這些的一件好事就是你甚至不需要「打開系統」。 – TheQuickBrownFox

相關問題