【问题标题】:F# sequence and array2d conversionF# 序列和 array2d 转换
【发布时间】:2015-08-09 15:48:47
【问题描述】:

我正在创建一个函数来将 Array2D 的 Squares 转换为字符串,然后将该字符串保存到文件中。此外,我还创建了一个加载函数,它将从文件中获取字符串并将该字符串转换为 Array2D。

Square 看起来像:type Square = { x : int; y : int; number : int; optionList : int list },并且还有一些用于创建和操作的函数。

//Getter functions
let getNumber S = S.number
let getXpos S = S.x        
let getYpos S = S.y
let getSquareList S = S.optionList

// createSquare creates a Square at position x y
let createSquare x y = { x=x; y=y; number = 0; optionList = [1..9]}

// createSquareFromScratch creates a Square where you decide all parameters
let createSquareFromScratch x y num li = { x=x; y=y; number = num; optionList = li}

// modifiedSquare creates a Square based on an old square
let modifiedSquare x y S = { x=x; y=y; number = getNumber S; optionList = getSquareList S }

我要保存的 Squares 部分是数字和 optionList,这将产生一个 10 元素长的字符串,首先是数字,然后是列表。该列表的长度可以是 0 到 9 个元素,因此如果列表短于 9 个元素,则其余部分可以用 0 填充。例如 5123900000 其中 5 是数字,1239 是列表,00000 是填充。

根据我的推理,函数应该因此以某种方式从 array2d 构建一个字符串,可能是通过使用内置的高阶函数,或者如果 array2d 中不存在适当的函数,则首先转换为序列,然后从那里使用适当的函数.

Square 位于 9x9 大 Array2D 中,它们从 Array 中获取的顺序将是它们在稍后的加载函数中加载的顺序(加载它们时会给它们适当的 x 和 y 值)。

如何将字符串转换为 array2d 的正方形并将 array2d 的正方形转换为字符串?

(我有很多无效的试错代码,但大部分都是非常糟糕且非常明显的测试。)例如:

let loadGame (gameAsString : string) =
    let tmp = List.ofSeq (gameAsString) |> Seq.cast<Square> |> Seq.toArray
    Array2D.init 9 9 (fun i j -> modifiedSquare i j (tmp.[((i+1)*(j+1) - 1)]))

let rec gameBoardToString (gameBoard : Square[,]) =
    match gameBoard.[0,0] with
    | x -> x.number.ToString() + x.optionList.ToString() 

【问题讨论】:

  • 这是学校作业还是真正的项目?通常,您不应该发明编码/序列化格式(除非是练习),而是使用现有格式,例如 JSON、XML 或 YAML(我最喜欢的是 JSON)。有现成的库可以在一个调用中为您进行序列化/反序列化。例如:newtonsoft.com/json
  • 这是一个我尝试通过创建数独游戏来学习函数式 f# 的项目。唯一的转换是当我将游戏板独立于其当前状态转换为字符串(保存到文件),然后如果用户想要加载旧游戏,则再次返回。但我会调查json!谢谢。

标签: arrays string f# converter


【解决方案1】:

要按照您描述的方式将数字数组转换为字符串,请使用String.Join

let optionsToStr<'a> (opts: seq<'a>) = System.String.Join( "", opts )

> optionsToStr [0..9]
val it : string = "0123456789"
> optionsToStr [true;false]
val it : string = "TrueFalse"

但是,只有当您保证所有数字都在 0..9 范围内时,才能将其解析回来 - 否则无法判断 "12" 是代表 [1;2] 还是代表 [12]。因此,您可能需要想出某种分隔符或其他方式来以文本形式构建数据。

这让我想到了下一点:通常,您不应该发明编码/序列化格式(除非是练习),而是使用现有格式,例如 JSON、XML 或 YAML(我最喜欢的是 JSON )。有现成的库可以在一次调用中为您进行序列化/反序列化。

例如查看JSON.NET:

let json = JsonConvert.SerializeObject( gameBoard )

// Here, I assume that typeof<gameBoard> = "Square list list"
let board = JsonConvert.DeserializeObject<Square list list>( json )

【讨论】:

  • 谢谢,这正是我想知道的,我会试试看!我还将更多地研究 JSON 和其他格式。以前从未使用过它们,但一定会阅读更多关于它们的信息:)
猜你喜欢
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 2010-11-09
  • 2015-05-21
  • 2018-09-29
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多