2015-11-05 73 views
2

我是F#的新手,我开始做一个简单的项目。F#将已映射的输入写入输出

我有大的txt文件,我处理 - 通常约1000万条记录。我想要做的是读取文件,过滤出一些特定的行,将字段映射到仅从原始文件中获取列的子集,然后输出结果。

的2个问题我有是:

  1. 如何基于在地图上进行筛选。该文件有大约30个字段。
  2. 我如何把地图的输出,并将其写入到一个新的TXT文件

//Open the file 
let lines = seq {use r = new StreamReader(kDir + kfName) 
    while not r.EndOfStream do yield r.ReadLine() } 

//Filter the file 
let sFilt = "Detached Houses,Upper Middle" 
let out1 = lines 
      |> Seq.filter (fun x -> x.Contains(sFilt)) 

//Write out the filtered file - this works great 
//val out1 : seq<string> 
File.WriteAllLines("c:\\temp\\out1.txt", out1) 


//Here is where I have an issue 
//I am trying to just get 2 of the columns to an output file 
//val out2 : seq<string * string> - this has a different patter than out1 
let out2 = out1 |> Seq.map (fun x2 -> x2.Split[|','|]) 
       |> Seq.map (fun x3 -> x3.[0], x3.[3]) 

我得到这条线下面的错误 - 我知道OUT1和OUT2是不同的。我该如何解决这种差异?

错误消息:

可能的过载:'File.WriteAllLines(path: string, contents: IEnumerable<string>) : unit'。类型约束不匹配。 seq<string * string>类型与IEnumerable<string>类型不兼容
类型'string''string * string'类型不匹配。

回答

2

您可以做的是将您的seq<string*string>映射回seq<string>

Seq.map (fun (str1, str2) -> sprintf "%s, %s" str1 str2) 

您只需添加到您现有的地图操作

let out2 = 
    out1 
    |> Seq.map (fun x2 -> x2.Split[|','|]) 
    |> Seq.map (fun x3 -> x3.[0], x3.[3]) 
    |> Seq.map (fun (str1, str2) -> sprintf "%s, %s" str1 str2) 

链之后,再一次,你有,你可以写信给你的文件串序列。

+0

这完美的作品。谢谢。 我已阅读输入文件并处理了我想要的记录。我想以某种方式获取文件中的列标题。 out1 seq在第一行有列名。我可以得到它并追加它吗? – nbt1032

2

fun x3 -> x3.[0], x3.[3]创建一个字符串元组string * string。您需要将它们连接起来,例如fun x3 -> sprintf "%s,%s" x3.[0] x3.[3](如果你想在输出中的逗号)或只是fun x3 -> x3.[0] + x3.[3]