当前位置: 首页 > 工具软件 > fsharp > 使用案例 >

使用Fsharp构建文件结构

赫连飞沉
2023-12-01

利用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对象,所以执行这两个函数几乎是不需要花费时间的,如果有优化也应该在这个时候进行。我在这里过滤了一些需要忽略的文件列表。

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


 类似资料: