f# - 在 F# 中解析中间有孔的列表的最惯用方法
问题描述
我正在解析一个以这种方式组织的 excel 文件:
header1
header2
data
data
[...]
data
one blank line
data
data
[...]
data
one blank line
所以,我们有一个标题,要跳过,一些可变长度的数据,一个空白行,一些可变长度的数据和一个空白行来标记感兴趣区域的结束。
这两个数据块以相同的方式解析,它们最终必须在一个列表中,但重要的是我知道中间空白行的索引(它是一个从中间处理的列表,要么朝向顶部或朝向底部)。
有两个警告:
- 顶部和底部的长度不同。
- 其中一侧可以是空的。
现在,我有一个不太干净的实现,因为它重复了代码:
let gridRowsUp =
gridExcel
|> List.skip 2
|> List.takeWhile (fun rowData -> rowData |> Seq.exists(fun x -> not (String.IsNullOrEmpty(x))))
|> List.mapi (fun index rowData -> parseGridLayer (index + 2) rowData)
// get the index of the middle row
let middleRow = 2 + gridRowsUp.Length
// get the bottom part of the grid
let gridRowsDown =
gridExcel
|> List.skip (1 + middleRow)
|> List.takeWhile (fun rowData -> rowData |> Seq.exists(fun x -> not (String.IsNullOrEmpty(x))))
|> List.mapi (fun index rowData -> parseGridLayer (index + 1 + middleRow) rowData)
let gridData = gridRowsUp @ gridRowsDown
理想情况下,我想一次性处理数据线,但跳过并记录中间空白行的位置。
我想过找到第一个空行并在没有它的情况下重建一个列表(因为我现在知道索引),但它很复杂,因为我需要找到第一个,然后找到第二个以知道在哪里停止(可以有一个下面有很多未使用的额外行)然后再次构建一个列表。在 F# 中删除列表中间的元素并不理想。
我怎样才能使它更精简?
解决方案
我认为循环会比重复代码更好。这段代码应该阐明逻辑。
// main dataset
let gridExcel = [
"header1"; "header2"; "data1"; "data2"; "data3"; "data4"; "";
"data5"; "data6"; "";
"data7"; "data8"; "data9"; "data10"; "";
"data11"; "data12"; "data13"; "data14"; "data15"; "";
"data16"; "data17"
]
let mutable blanks = [] // index of blank lines
let mutable allrows = [] // all non-blanks rows (no headers)
let mutable ctr = 2 // row index of main data
let mutable run = true
while (run) do
let gridRows =
gridExcel
|> List.skip ctr // skip previous data
|> List.takeWhile (fun rowData -> not (String.IsNullOrEmpty(rowData))) // while not empty line
|> List.mapi (fun index rowData -> "xx" + rowData) // process entry
allrows <- allrows@gridRows // add to list total
ctr <- ctr + gridRows.Length // add to skip ctr
if (ctr < gridExcel.Length) then blanks <- blanks@[ctr] // store blank line index
ctr <- ctr + 1 // skip blank line
if (ctr >= gridExcel.Length) then run <- false // done main list
printfn "Blanks: %A\n" blanks // indexes of blanks lines
printfn "Processed Data:\n%A" allrows // all processed rows
输出
Blanks: [6; 9; 14; 20]
Processed Data:
["xxdata1"; "xxdata2"; "xxdata3"; "xxdata4"; "xxdata5"; "xxdata6"; "xxdata7";
"xxdata8"; "xxdata9"; "xxdata10"; "xxdata11"; "xxdata12"; "xxdata13";
"xxdata14"; "xxdata15"; "xxdata16"; "xxdata17"]
推荐阅读
- python - 安装 PyTorch 1.4 的问题 - “没有找到与 torch===1.4.0 匹配的发行版”
- python - ValueError: y 在 0 类中只有 1 个样本,协方差定义不正确。而QDA分类
- php - 使用 woocommerce 产品详细信息污染数组或 json
- r - 使用空间将一列溢出
- node.js - 无法获取/NodeJS - Heroku - ReactJS
- jquery - DataTable 搜索过滤器始终返回“未找到匹配记录”
- java - 用系列确定双精度的平方根
- reason - 如何将 Js.Json.t 转换为 Js.t('a)?
- php - 未定义的变量 Laravel 路由
- google-app-engine - 使用本地开发服务器运行烧瓶(python3)appengine