首页 > 解决方案 > F#:如何以函数方式遍历字符串数组列表(字符串 [] 列表)

问题描述

我是 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# 我感觉真的卡住了。

感谢您的帮助

标签: arrayslistloopsf#iteration

解决方案


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

我已经以这样一种方式实现了 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."

推荐阅读