使用Fsharp构建文件结构

利用fsharp构建文件结构。

open System.IO
type FileUnit = 
    | Empty 
    | File of string * FileAttributes
    | Directory of string * FileAttributes * FileUnit
    | FDList of seq<FileUnit>
    | FileUnit of FileUnit*FileUnit

let rec getFiles4 path =
    match DirectoryInfo(path).Exists with
    | false -> Empty
    | _     -> match DirectoryInfo(path).Attributes &&& FileAttributes.Directory with
               | FileAttributes.Directory -> let dlst = match Directory.GetDirectories(path).Length with
                                                        |0 -> Empty
                                                        |1 -> Directory(path, DirectoryInfo(path).Attributes, Directory.GetDirectories(path).[0] |> getFiles4)
                                                        |_ -> FDList(seq{
                                                                         for elem in Directory.GetDirectories(path) do               
                                                                             yield Directory(elem, DirectoryInfo(elem).Attributes, getFiles4 elem)})
                                             let flst = match Directory.GetFiles(path).Length with
                                                        |0 -> Empty
                                                        |1 -> File(path, DirectoryInfo(path).Attributes)
                                                        |_ -> FDList(seq{
                                                                        for elem in Directory.GetFiles(path) do
                                                                            yield File(elem, DirectoryInfo(elem).Attributes)})
                                             FileUnit(flst, dlst)
               | _ -> FileUnit(File(path, DirectoryInfo(path).Attributes), Empty )
文件系统是由文件和文件夹组成的。上面的可区分联合引入了几个额外的抽象,对象列表,文件及文件夹组合。回头再来看,解决方案把问题想复杂了。

文件系统最大的特点便是其递归的定义,文件夹含文件和文件夹,可区分联合在这里描述概念再合适不过了。

新的版本

open System
open System.IO
open System.Threading
open System.Threading.Tasks
open System.Diagnostics

#if INTERACTIVE
#time
#endif

type FileUnit = 
    | FileElem of string * DirectoryInfo
    | DirectoryElem of string * DirectoryInfo * seq<FileUnit>

let rec getFiles path = 
    match Directory.Exists(path),File.Exists(path) with
    |false, true -> FileElem(path, DirectoryInfo(path))
    |true, false -> DirectoryElem(path, DirectoryInfo(path), 
                        Directory.GetFiles(path) |> Seq.collect (fun it -> [FileElem(it, DirectoryInfo(it))])
                        |> Seq.append <| 
                        (Directory.GetDirectories(path) |> Seq.collect (fun it -> [ it |> getFiles ])))
    |_           -> failwith("can not get file or directory")
                            
let rec getFileList fu (ignoreset:Set<string>)= 
    seq{
        match fu with
        |FileElem(name, info) -> yield name, info
        |DirectoryElem(name, info, lst) -> 
            if not (ignoreset.Contains(info.Name)) then
                yield name, info; yield! (lst |> Seq.collect  (fun x -> getFileList x ignoreset))
    }
新版本中文件单元只存在两种情况,文件和文件夹。在进行模式匹配的时候需要做的事也会少一些。getFileList将树形的文件结构铺展为一个1维列表。由于生成列表的过程中使用了Seq对象,所以执行这两个函数几乎是不需要花费时间的,如果有优化也应该在这个时候进行。我在这里过滤了一些需要忽略的文件列表。

原本的想法还是有些乱,改进的空间总是存在的,此为止。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值