【问题标题】:F# Type casting an array of stringsF# 类型转换字符串数组
【发布时间】:2017-02-20 23:42:40
【问题描述】:

我有 2 个数组。数组 1 是一个包含类型名称的字符串数组。

所以数组 1 的内容是这样的:

["nvarchar";"nvarchar";"date";"nvarchar"] //these are all strings

数组 2 是另一个字符串数组,其内容如下所示:

["Jackson";"Sentzke";"1991-04-19T00:00:00";"Jackson Sentske"]

我的问题是数组 2 中的所有值都是字符串,我希望它们属于数组 1 中的类型。有没有办法可以使用数组 1 中的字符串对数组 2 中的字符串进行类型转换?

【问题讨论】:

  • 首先,显然这些是 SQL 列类型,而不是 .NET 类型。其次,你不能真正拥有不同类型的数组。第三,这就是类型提供程序的用途,而 SQLProvider 有一个漂亮的 .Mapto 方法可以做到这一点。您应该将其存储在一组记录中,这样您的生活就会轻松得多。

标签: arrays string casting f#


【解决方案1】:

这是一个低级的解决方案,因为这一切的发展方向并不是很明显,但如果你需要的只是让你的字符串成为 db 类型,那么 T-SQL 有Cast and Convert还有this给你。所以你可以说CAST ("1991-04-19T00:00:00" AS date)

【讨论】:

    【解决方案2】:

    其实你这里有几个问题。

    逗号创建元组 你的代码

    ["nvarchar","nvarchar","date","nvarchar"]
    

    不是string list,而是(string * string * string * string) list

    如果要创建string list,则必须使用分号;

    现在,如果您知道您的代码始终具有与您想要的确切类型相同的确切数量的元组元素,那么您可以这样做

    type RowItems = string * string * DateTime * string
    type Rows = RowItem list
    

    现在,如果您的问题包括不同大小的行,并且您希望从 SQL 数据类型转换为 SQL 数据类型,那么使用 Discriminate Unions 的方法可能会有所帮助。

    type SQLDataType =
       | VarChar of string
       | Date of DateTime
    
    type Row = SQLDataType list
    type Rows = RowItem list
    

    那么用法应该是这样的

    let row = 
        [
            VarChar "Jackson";
            VarChar "Sentzke";
            Date DateTime.parse("1991-04-19T00:00:00");
            VarChar "Jackson Sentske"
        ]
    

    最后,您应该编写一些转换函数,将其与您的 SQL 数据相互转换

    let fromSQL (s:string) : SQLDataType = ...
    let toSQL (s:SQLDataType) : string = ...
    

    我希望这会有所帮助。

    【讨论】:

    • 感谢您的评论。它会帮助某人。我以为这会对我有所帮助,但后来我意识到我问错了问题。
    【解决方案3】:

    正如@s952163 指出的那样,您似乎正在尝试从数据库中读取数据,在这种情况下,有比自己尝试更好的选择。不过,如果从表面上看 OP,只是为了勾勒出一个可能的解决方案,这是一种解决方法。

    由于列出的类型不是 .NET 类型,也许最好定义一个自定义类型来保存这些值:

    open System
    
    type DbType = NVarChar of string | DT of DateTime
    

    如果您愿意,可以向DbType 添加更多案例。

    使用active patterns,您可以编写一个函数来转换单个候选:

    // string * string -> string option
    let (|NVarChar|_|) = function
        | "nvarchar", (x : string) -> Some x
        | _ -> None
    
    // string * string -> DateTime option
    let (|DT|_|) (typeHint, value) =
        match (typeHint, DateTime.TryParse value) with
        | "date", (true, dt) -> Some dt
        | _ -> None
    
    // string * string -> DbType option    
    let convertPair = function
        | NVarChar x -> Some (NVarChar x)
        | DT x -> Some (DT x)
        | _ -> None
    

    使用活动模式并不是绝对必要的,但我认为它使我能够很好地分解问题。

    现在您可以声明类型列表和值之一,将它们压缩在一起以获得解释值列表:

    > let types = ["nvarchar"; "nvarchar"; "date"; "nvarchar"];;    
    val types : string list = ["nvarchar"; "nvarchar"; "date"; "nvarchar"]
    
    > let values = ["Jackson"; "Sentzke"; "1991-04-19T00:00:00"; "Jackson Sentske"];;    
    val values : string list =
      ["Jackson"; "Sentzke"; "1991-04-19T00:00:00"; "Jackson Sentske"]
    
    > let converted = List.zip types values |> List.choose convertPair;;    
    val converted : DbType list =
      [NVarChar "Jackson"; NVarChar "Sentzke"; DT 19.04.1991 00:00:00;
       NVarChar "Jackson Sentske"]
    

    请注意,typesvalues 都具有 string list 类型。在 OP 中,它们是 (string * string * string * string) list,我认为这是一个错误。

    【讨论】:

    • 是的,这是一个错误。谢谢你的纠正。也感谢您的评论。它会帮助某人。我以为这会对我有所帮助,但后来我意识到我问错了问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 2012-02-15
    • 2019-02-09
    • 2017-11-29
    • 2014-08-30
    • 2014-12-08
    相关资源
    最近更新 更多