F #: Сведение последовательности последовательностей в один Seq - PullRequest
4 голосов
/ 19 марта 2012

Я пытаюсь создать одну последовательность, которая содержит содержимое нескольких файлов, чтобы ее можно было отсортировать и затем передать в графический компонент.Однако я застрял, пытаясь сложить содержимое каждого файла вместе.Приведенный ниже псевдокод не будет компилироваться, но, надеюсь, покажет намерение того, чего я пытаюсь достичь.

Любая помощь, с благодарностью.

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

Ответы [ 2 ]

12 голосов
/ 19 марта 2012

По сути, вы пытаетесь переопределить Files.Readlines , который возвращает содержимое файла как seq<string>.Затем это можно объединить с Seq.concat:

let res = Directory.EnumerateFiles(@"D:\test_Data","*.csv",SearchOption.AllDirectories)
          |> Seq.map File.ReadLines 
          |> Seq.concat
4 голосов
/ 20 марта 2012

Чтобы устранить проблему в исходном подходе, вам нужно использовать 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! добавляет все элементы последовательности к результату.

...