2016-12-01 77 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

相关问题