【问题标题】:F#: How to iterate through a List of Arrays of Strings (string [] list) the functional wayF#:如何以函数方式遍历字符串数组列表(字符串 [] 列表)
【发布时间】:2020-09-04 14:54:03
【问题描述】:

我是 F# 的新手, 我有一个包含数组的列表,每个数组包含 7 个字符串。 我想循环遍历数组并稍后执行某种 Array.map,

但是我的问题是我无法将单个数组发送到其他函数。

我不想使用 for 循环,而是专注于仅使用管道和映射的函数式方式。

let stockArray =
    [[|"2012-03-30"; "32.40"; "32.41"; "32.04"; "32.26"; "31749400"; "32.26"|];
    [|"2012-03-29"; "32.06"; "32.19"; "31.81"; "32.12"; "37038500"; "32.12"|];
    [|"2012-03-28"; "32.52"; "32.70"; "32.04"; "32.19"; "41344800"; "32.19"|];
    [|"2012-03-27"; "32.65"; "32.70"; "32.40"; "32.52"; "36274900"; "32.52"|];]

let tryout =
    stockArray
    |> List.iter;;

输出抱怨 List.iter:

error FS0001: Type mismatch. Expecting a
'string [] list -> 'a' but given a
'('b -> unit) -> 'b list -> unit' 
The type 'string [] list' does not match the type ''a -> unit'

在尝试 Array.iter 时,同样的区别:

 error FS0001: Type mismatch. Expecting a
'string [] list -> 'a' but given a
'('b -> unit) -> 'b [] -> unit' 
The type 'string [] list' does not match the type ''a -> unit'

在 C# 中,我会简单地使用 foreach 开始处理我的数组,一次处理一个,但使用 F# 我感觉真的卡住了。

感谢您的帮助

【问题讨论】:

  • List.iter 需要一个函数,它将为列表的每个成员调用,看看它的签名。
  • 确实,对不起,我对签名感到困惑。我正在努力掌握它告诉我的内容。所以可能Iter不是我想要的,因为它需要吐出“Unit”......我需要吐出“string []”对吗?

标签: arrays list loops f# iteration


【解决方案1】:

即使有额外的 cmets,问题也不清楚。无论如何,我认为您最终将能够从这个答案中找出您的需求。

我以这样一种方式实现了 parseDate 和 parseFloat,我希望它可以在任何机器上使用给定的数据,无论语言环境如何。您可能需要其他东西用于您的生产应用程序。此外,theInt 的计算方式可能不是您想要的。

如您所见,List.iter 将数据转换为unit,从而有效地丢弃数据。那么这有什么意义呢?当在管道序列中使用时,它通常放在最后,经常做一些涉及副作用(例如打印数据)或可变数据操作(例如用项目填充可变列表)的工作。我建议你研究 List、Array、Seq 和 Option 模块中的函数,看看它们是如何用于转换数据的。

open System
open System.Globalization

let stockArray =
    [
        [| "2012-03-30"; "32.40"; "32.41"; "32.04"; "32.26"; "31749400"; "32.26" |]
        [| "2012-03-29"; "32.06"; "32.19"; "31.81"; "32.12"; "37038500"; "32.12" |]
        [| "2012-03-28"; "32.52"; "32.70"; "32.04"; "32.19"; "41344800"; "32.19" |]
        [| "2012-03-27"; "32.65"; "32.70"; "32.40"; "32.52"; "36274900"; "32.52" |]
    ]

type OutData = { TheDate: DateTime; TheInt: int }

let parseDate s = DateTime.ParseExact (s, "yyyy-MM-dd", CultureInfo.InvariantCulture)

let parseFloat s = Double.Parse (s, CultureInfo.InvariantCulture)

let myFirstMap (inArray: string[]) : OutData =
    if inArray.Length <> 7 then
        failwith "Expected array with seven strings."
    else
        let theDate = parseDate inArray.[0]
        let f2 = parseFloat inArray.[2]
        let f3 = parseFloat inArray.[3]
        let f = f2 - f3
        let theInt = int f
        { TheDate = theDate; TheInt = theInt }

let tryout =
    stockArray
    |> List.map myFirstMap

以下是 myFirstMap 的替代实现。我想有些人会说它更惯用,但我只想说你喜欢使用什么取决于你对未来可能的发展的期望。

let myFirstMap inArray =
    match inArray with
    | [| sDate; _; s2; s3; _; _; _  |] ->
        let theDate = parseDate sDate
        let f2 = parseFloat s2
        let f3 = parseFloat s3
        let f = f2 - f3
        let theInt = int f
        { TheDate = theDate; TheInt = theInt }
    | _ -> failwith "Expected array with seven strings."

【讨论】:

    【解决方案2】:

    但是我的问题是我无法将单个数组发送到其他函数

    List.map 和类似的函数允许您精确地做到这一点 - 您不需要自己迭代列表。

    例如,这将只返回列表中每个数组的第一个元素:

    stockArray
        |> List.map (fun x -> x.[0])
    

    您可以将传递给 List.map 的函数替换为对一个数组进行操作并返回某个值的任何函数。

    【讨论】:

      【解决方案3】:

      管道运算符|&gt; 用于将f x 写为x |&gt; f

      List.iter的签名是:

      action: ('a -> unit) -> list: ('a list) -> unit
      

      你给它一个动作,然后是一个列表,它给你一个void

      你可以这样理解:当你给List.iter一个动作时,它的类型将是

      list: ('a list) -> unit
      

      您可以向其传递列表的函数。

      因此,当您编写stockArray |&gt; List.iter 时,您实际上试图代替操作的是您的列表 - 这就是错误。所以传入一个动作:

      let tryout = List.iter (fun arr -> printfn "%A" arr) stockArray
      

      可以改写为:

      let tryout = stockArray |> List.iter (fun arr -> printfn "%A" arr) 
      

      【讨论】:

      • 谢谢,所以 List.iter 并不是我想要的。本质上,我想输入一个数组列表,然后输出一个数组列表。输出数组必须是日期 (item[0]) 和一个 int (item[2] - item[3])。知道什么功能适合使用吗?
      猜你喜欢
      • 2018-05-06
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      • 2019-06-06
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2014-09-19
      相关资源
      最近更新 更多