F#中的文本解析和嵌套集合转置

时间:2013-08-20 16:51:17

标签: collections f# nested text-parsing transpose

我从csv文件中解析数据,如下所示:

X,..,..,Dx,..,..
Y,..,..,Dy,..,..
X,..,..,Dx,..,..
Y,..,..,Dy,..,..
X,..,..,Dx,..,..
Y,..,..,Dy,..,..

每一行都是我定义并与FileHelpers一起使用的I类型数组的元素。这可能是不相关的,但我包含了这个问题,有人知道我在使用FileHelpers的过程的这个阶段可以做的一些技巧。

我只对X,Dx和Y,Dy对感兴趣 数据可能不只是X& Y eg ..(X,Dx); (Y,DY); (Z,DZ); ...

我将调用字母数nL

目标是通过处理具有SUM(nIterations)* nL元素的所有D的数组来获得每个组的Dx,Dy,...的平均值。

我有一系列迭代次数:

let nIterations = [2000; 2000; 2000; 1000; 500; 400; 400; 400; 300; 300]

对于这些数字中的每一个,我都会有那么多“信件组”。因此,nIterations。[0]感兴趣的数据行是0行到(nIterations。[0] * nL)

要获取nIterations的感兴趣的行。[i],我列出了一个“nis”列表,这是在nIterations上执行扫描操作的结果。

let nis = List.scan (fun x e -> x + e) 0 nIterations

然后隔离nItertions。[i] group ..

let group = Array.sub Ds (nis.[i]*nL) (nIterations.[i]*nL)

以下是整个事情:

nIterations |> List.mapi (fun i ni ->
    let igroup = Array.sub Ds (nis.[i]*nL) (ni*nL)
    let groupedbyLetter = (chunk nL igroup)

    let sums = seq { for idx in 0..(nL - 1) do
                         let d = seq { for g in groupedbyLetter do 
                                           yield (Seq.head (Seq.skip idx g)) }
                         yield d |> Seq.sum }

    sums |> Seq.map (fun x -> (x / (float ni))) ) |> List.ofSeq

那个“块”功能是我在SO上找到的功能:

let rec chunk n xs =
    if Seq.isEmpty xs then Seq.empty
    else
        let (ys,zs) = splitAt n xs
        Seq.append (Seq.singleton ys) (chunk n zs)

我已经验证了这项工作,并得到了我想要的东西 - 尺寸为nLterations.Length collection的尺寸nL集合。

问题在于速度 - 这仅适用于小型数据集;在我给出的例子中,我正在使用的尺寸太大了。它在块功能上“挂起”。

所以我的问题是:如何提高整个过程的速度? (和/或)做“转换”的最佳方式(或至少更好)

我认为我可以:

  • 尝试重新排列数据,因为我正在
  • 中阅读
  • 尝试直接索引元素
  • 尝试将流程分解为更小的阶段或“通过”
  • ???

2 个答案:

答案 0 :(得分:1)

我明白了。

let averages =
    (nIterations |> List.mapi (fun i ni ->
        let igroup = Array.sub Ds (nis.[i]*nL) (ni*nL)
        let groupedbyLetter = 
            [| for a in 1..nL..igroup.Length do 
                   yield igroup.[(a - 1)..(a - 1)+(nL-1)] |]

        [| for i in 0..(nL - 1) do
               yield [| for j in 0..(groupedbyLetter.Length - 1) do
                            yield groupedbyLetter.[j].[i] |] 
               |> Array.average |]) )

let columns = [| for i in 0..(nL - 1) do
                     yield [| for j in 0..(nIterations.Length - 1) do
                                  yield averages.[j].[i] |] 
                     |]

“columns”功能只是再次转置数据,因此我可以轻松打印..

               ----Average Ds----
nIterations       X    Y    Z
   2000          0.2  0.7  1.2
    ...          ...  ...  ...
    ...          ...  ...  ...

e.g。平均回报

[[x1,y1,z1,..], [x2,y2,z2,..], ... ]

和列给了我

[ [x1,x2,..], [y1,y2,..], [z1,z2,..], ...]

答案 1 :(得分:0)

The accepted answer对于您发现chunk函数包含更高效版本的问题。