【问题标题】:read strings from console without for loop从控制台读取字符串而不使用 for 循环
【发布时间】:2016-06-19 17:48:23
【问题描述】:

是否有任何优雅的函数式方法可以从控制台输入读取 N 个字符串? F# for fun and profit 建议避免使用 for 循环,所以我使用了递归,但它看起来又丑又长。

代码说明:我需要从控制台读取几个字符串(确切的数字在控制台输入的第一行中指定),将它们连接起来并转换为整数数组。

let rec recReadline n =
    match n with
        | 0 -> ""
        | _ -> let x = n - 1
               " " + Console.ReadLine() + recReadline x 

let getArrayOfIntFromConsole = 
    let x = Console.ReadLine() |> int |> recReadline
    let trimmedString = x.Trim()
    let numArray = trimmedString.Split ' ' |> Array.map(int)
    numArray

我正在学习 f#,对于菜鸟问题​​抱歉。

更新1

感谢您的回复!这是来自黑客级别的任务:https://www.hackerrank.com/challenges/diagonal-difference。起初我决定将输入和算法逻辑分开,并创建了这篇文章。我对问题的上下文描述不够清楚,建议使用 Array.Init。它对我没有帮助,因为输入字符串由许多用空格分隔的整数组成。我用 Array.Init 将一个回复标记为正确答案,因为它是我糟糕的问题的正确答案。

我决定在一个函数中读取控制台和计算,它对我来说没问题。 我的最终代码:

open System

let rec recDiagDif recCounter primaryDiagSum secondDiagSum =
    match recCounter with
        | 0 -> primaryDiagSum - secondDiagSum |> abs
        | _ -> let arrayInt = Console.ReadLine().Split ' ' |> Array.map(int)
               recDiagDif (recCounter-1)
                          (primaryDiagSum + arrayInt.[arrayInt.Length - recCounter])
                          (secondDiagSum + arrayInt.[recCounter-1])

[<EntryPoint>]
let main argv =
    let matrixSize = Console.ReadLine() |> int
    printf "%A" (recDiagDif matrixSize 0 0)
    0

如果您知道如何改进代码,请随时发表评论。

【问题讨论】:

标签: f#


【解决方案1】:

我倾向于建议将控制台输入保留为某种集合,而不是仅转换为扁平字符串然后在空白处再次拆分。

let readNLines n =  Array.init n (fun _ -> Console.ReadLine())

let getArrayOfIntFromConsole() = 
    let lines = Console.ReadLine() |> int |> readNLines
    let numArray = lines |> Array.map(int)
    numArray

【讨论】:

    【解决方案2】:

    你可以这样做:

    open System
    
    let getArrayOfIntFromConsole () = 
        let readLines n = Array.init n (fun _ -> System.Console.ReadLine ())
        Console.ReadLine () |> int |> readLines |> Array.map int
    

    演示(FSI):

    > getArrayOfIntFromConsole ();;
    3
    1
    42
    1337
    val it : int [] = [|1; 42; 1337|]
    

    【讨论】:

    • 如何在行数未知且没有转义序列的情况下做到这一点?
    • @rowRobot 那要看怎么退出了。
    • 这完全是为了解决一个 HackerRank 问题,其中输入作为一堆整数提供给标准输入,每行一个。您必须先登录才能看到此页面hackerrank.com/challenges/fp-list-replication/problem
    【解决方案3】:

    您可以创建一个从Console.ReadLine 馈送的无限序列,然后像这样获取第一个n 元素

    let readNStrings n =                       
        fun _ -> Console.ReadLine()
        |> Seq.initInfinite
        |> Seq.take n
    

    【讨论】:

    • 我不确定这是一个好主意,懒惰的评估和 IO 对于经验丰富的开发人员来说是一个危险的组合,更不用说 F# 新手了。无法保证Console.ReadLine() 在此示例中执行了多少次,甚至何时执行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    • 2014-12-06
    • 1970-01-01
    • 2013-11-20
    • 2018-06-18
    • 1970-01-01
    相关资源
    最近更新 更多