2012-03-19 39 views
4

我想要构建一个包含多个文件内容的单个序列,以便它可以被排序然后传递给一个图形组件。不过,我试图将每个文件的内容放在一起。下面的伪代码不会编译,但希望会显示我想要实现的目的。F#:将一系列序列拼合成一个Seq

任何帮助,非常感谢。

open System.IO 

let FileEnumerator filename = seq { 
     use sr = System.IO.File.OpenText(filename) 
      while not sr.EndOfStream do 
      let line = sr.ReadLine() 
      yield line 
} 

let files = Directory.EnumerateFiles(@"D:\test_Data\","*.csv",SearchOption.AllDirectories) 

let res = 
    files 
     |> Seq.fold(fun x item -> 
     let lines = FileEnumerator(item) 
     let sq = Seq.concat x ; lines 
     sq 
    ) seq<string> 

printfn "%A" res 
+4

您是否在寻找Seq.collect http://msdn.microsoft.com/en-us/library/ee340468.aspx? – 2012-03-19 18:13:24

回答

12

你基本上是试图重新实现Files.Readlines,返回文件内容seq<string>。然后可以用Seq.concat级联:

let res = Directory.EnumerateFiles(@"D:\test_Data","*.csv",SearchOption.AllDirectories) 
      |> Seq.map File.ReadLines 
      |> Seq.concat 
4

要在原来的办法解决这个问题,你需要使用Seq.append,而不是Seq.concat。为fold初始值应该是一个空序列,这可以写成Seq.empty

let res = 
    files |> Seq.fold(fun x item -> 
     let lines = FileEnumerator(item) 
     let sq = Seq.append x lines 
     sq) Seq.empty 

如果你想使用Seq.concat,你必须写Seq.concat [x; lines],因为concat预计序列的顺序进行级联。另一方面,append只需要两个序列,因此在这里使用更容易。

另一个(简单)的方式来连接所有的线是在序列表达式中使用yield!

let res = 
    seq { for item in files do 
      yield! FileEnumerator(item) } 

这样通过遍历所有文件和文件将所有线(按顺序)创建了一个序列到结果序列。 yield!构造将所有元素的sequenece添加到结果中。