我已经用谷歌搜索并阅读了,并且正在尝试找到一种“正确”的方法来做到这一点,但是我在 SO 上阅读的每个问题似乎都有完全不同的答案。
这是我的问题的要点。文件具有三元组序列的类型签名(a:string,b:string,c:Int64)。作为 f# 的新手,我仍然不能流利地表达类型签名(或者就此而言理解它们)。a 是文件名,b 是内部标识符,c 是表示文件长度(大小)的值。baseconfig 是代码前面的字符串。
ignore(files
|> Seq.filter( fun(x,y,z) -> y = baseconfig) // used to filter only files we want
|> Seq.fold( fun f n ->
if( (fun (_,_,z) -> z) n > 50L*1024L*1024L) then
zipfilex.Add((fun (z:string, _, _) -> z) n)
printfn("Adding 50mb to zip")
zipfilex.CommitUpdate()
zipfilex.BeginUpdate()
("","",0L)
else
zipfilex.Add((fun (z, _, _) -> z) n)
("", "", (fun (_, _, z:Int64) -> z) n + (fun (_, _, z:Int64) -> z) f)
) ("","",0L)
)
这段代码应该做的是遍历 中的每个文件files
,将其添加到 zip 存档中(但不是真的,它只是在稍后提交的列表中),当文件超过 50MB 时,提交当前待处理的文件到 zip 存档。添加文件很便宜,提交很昂贵,所以我尝试通过批处理来降低成本。
到目前为止,代码有点工作......除了当它接近 150MB 的提交文件时我得到的 ObjectDisposedException。但我不确定这是进行此类操作的正确方法。感觉就像我正在Seq.fold
以非常规的方式使用,但是,我不知道有更好的方法来做到这一点。
额外的问题:有没有更好的方法从元组中剔除值?fst 和 snd 仅适用于 2 值元组,我意识到您可以定义自己的函数,而不是像我那样内联它们,但似乎应该有更好的方法。
更新:我之前的折叠尝试,我不明白为什么我不能只使用 Int64 作为累加器。原来我错过了一些关键的括号。下面是更简单的版本。也消除了所有疯狂的元组提取。
ignore(foundoldfiles
|> Seq.filter( fun (x,y,z) -> y = baseconfig)
|> Seq.fold( fun (a) (f,g,j) ->
zipfilex.Add( f)
if( a > 50L*1024L*1024L) then
printfn("Adding 50mb to zip")
zipfilex.CommitUpdate()
zipfilex.BeginUpdate()
0L
else
a + j
) 0L
)
更新 2:我将不得不采用命令式解决方案,F# 以某种方式重新输入此代码块,在 zip 文件在其后的语句中关闭之后。这解释了 ObjectDisposedException。不知道这是如何工作的或为什么。