サブフォルダを含む、フォルダ内のファイルの取得(F#)
下記のようなフォルダ構造があった際に、file1.txt、file2.txt、file1_1.txtのパスを取得する関数をF#で実装します。
breadthFirstSearch
汎用的な幅優先探索を実装します。
開始点と、要素から子要素を取得する関数を入力とします。
Queueを用いて手続き的な実装をしました。
module Seq = let breadthFirstSearch (children : 'a -> 'a seq) (root : 'a) = seq { let queue = System.Collections.Generic.Queue<'a>([ root ]) while 0 < queue.Count do let item = queue.Dequeue() children item |> Seq.iter queue.Enqueue yield item }
breadthFirstSearch(Seqモジュールのみで実装)
参考例として、whileを使わずに実装してみました。
module Seq = let breadthFirstSearch (children : 'a -> 'a seq) (root : 'a) = Seq.initInfinite id |> Seq.scan (fun queue _ -> queue.Tail @ (children queue.Head |> Seq.toList)) [ root ] |> Seq.takeWhile (List.isEmpty >> not) |> Seq.map List.head
descendantFiles
フォルダを入力で受け取り、ファイルパスのSeqを返す関数を実装します。
open System.IO let descendantFiles path = Seq.breadthFirstSearch Directory.EnumerateDirectories path |> Seq.collect Directory.EnumerateFiles
動作確認
FolderBrowserDialogを利用するため、System.Windows.Forms.dllを参照に追加します。
[<EntryPoint>] open System.Windows.Forms let main argv = use dialog = new FolderBrowserDialog() if dialog.ShowDialog() = DialogResult.OK then descendantFiles dialog.SelectedPath |> Seq.iter (printfn "%s")