有条件地在F#的前进管道中应用过滤器?

时间:2013-07-23 23:06:42

标签: f# conditional-statements

我从CSV文件中获取一系列记录。我希望选择按日期和类型过滤这些记录,并可选择合并符合特定条件的记录。可选择使用Seq.filter按日期和类型进行过滤。但是,我想选择合并符合某些标准的记录。我有功能工作,我只是无法弄清楚如何选择将其应用于结果序列。我不能使用Seq.filter,因为合并操作对整个序列一次不在一个项目上。我可以用一个中间变量解决它,我只是想知道是否有一种优雅的惯用方法来处理它。

基本上我想知道一种在前向管道序列中有条件地应用链的一个(或多个)部分的方法。

这就是我想要的伪代码(options保存命令行参数):

let x =
    getRecords options.filePath
    |> Seq.filter (fun r -> if options.Date.HasValue then
                            r.Date.Date = options.Date.Value.Date else true)
    |> Seq.filter (fun r -> if not(String.IsNullOrEmpty(options.Type)) then
                            r.Type = options.Type else true)
    if options.ConsolidateRecords then
        |> consolidateRecords

3 个答案:

答案 0 :(得分:9)

您可以在if ... else子句中使用带有标识函数的else表达式:

let x =
    getRecords options.filePath
    |> (* ... bunch of stuff ... *)
    |> (if options.ConsolidateRecords then consolidateRecords else id)
    |> (* ... optionally more stuff ... *)

答案 1 :(得分:5)

我会做像

这样的事情
let x =
    getRecords options.filePath
    |> Seq.filter (fun r -> if options.Date.HasValue then
                            r.Date.Date = options.Date.Value.Date else true)
    |> Seq.filter (fun r -> if not(String.IsNullOrEmpty(options.Type)) then
                            r.Type = options.Type else true)
    |> fun x ->
         if options.ConsolidateRecords then x |> consolidateRecords
         else ....

答案 2 :(得分:3)

您还可以隐藏先前的x定义:

let x =
    getRecords options.filePath
    |> Seq.filter (fun r -> 
        not options.Date.HasValue || r.Date.Date = options.Date.Value.Date)
    |> Seq.filter (fun r -> 
        String.IsNullOrEmpty(options.Type) || r.Type = options.Type)
let x = if options.ConsolidateRecords then consolidateRecords x else x