我的数据是SEQUENCE:
[(40,"TX");(48,"MO");(15,"TX");(78,"TN");(41,"VT")]
我的代码如下:
type Csvfile = CsvProvider<somefile>
let data = Csvfile.GetSample().Rows
let nullid row =
row.Id = 15
let otherid row =
row.Id= 40
let iddata =
data
|> Seq.filter (not nullid)
|> Seq.filter (not otherid)
我创建了这些函数。
然后我想调用那些函数的“not”来过滤它们。
但问题是我在前两个函数中遇到“row.Id”错误,因为你只能用一个类型来做。
如何解决此问题,以便我能够成功完成此任务。
我的结果应该是以下序列:
[(48,"MO);(78,"TN");(41,"VT")]
答案 0 :(得分:6)
您可以使用>>
运算符来组合这两个函数:
let iddata =
data
|> Seq.filter (nullid >> not)
|> Seq.filter (othered >> not)
请参阅Function Composition and Pipelining。
或者你可以使它更明确:
let iddata =
data
|> Seq.filter (fun x -> not (nullid x))
|> Seq.filter (fun x -> not (othered x))
您可以看到实际操作:
let input = [|1;2;3;4;5;6;7;8;9;10|];;
let is3 value =
value = 3;;
input |> Seq.filter (fun x -> not (is3 x));;
input |> Seq.filter (not >> is3);;
他们都打印val it : seq<int> = seq [1; 2; 4; 5; ...]
答案 1 :(得分:1)
请参阅下面的MCVE在您的情况下可能会看到的内容,对于fsx文件,您可以使用Fsharp.Data
引用#r
dll,对于已编译的项目,只需引用dll即可打开它。
#if INTERACTIVE
#r @"..\..\SO2018\packages\FSharp.Data\lib\net45\FSharp.Data.dll"
#endif
open FSharp.Data
[<Literal>]
let datafile = @"C:\tmp\data.csv"
type CsvFile = CsvProvider<datafile>
let data = CsvFile.GetSample().Rows
最后,这是你想要实现的目标:
data
|> Seq.filter (fun x -> x.Id <> 15)
|> Seq.filter (fun x -> x.Id <> 40)
//val it : seq<CsvProvider<...>.Row> = seq [(48, "MO"); (78, "TN"); (41, "VT")]
执行此操作的一种方法是使用SRTP,因为它们允许进行结构类型化,其中类型取决于其形状,例如在这种情况下具有Id
属性。如果需要,可以为两个数字15和40定义辅助函数,并在过滤器中使用它,就像在第二个示例中一样。然而,SRTP语法有点奇怪,它设计用于需要将函数应用于具有一些相似性的不同类型(基本上类似于接口)的用例。
let inline getId row =
(^T : (member Id : int) row)
data
|> Seq.filter (fun x -> (getId x <> 15 ))
|> Seq.filter (fun x -> (getId x <> 40))
//val it : seq<CsvProvider<...>.Row> = seq [(48, "MO"); (78, "TN"); (41, "VT")]
现在回到原来的帖子,因为你正确地指出你的函数会显示错误,因为你将它定义为通用的,但它需要在特定的Csv行类型(具有Id属性)上运行。这很容易修复,只需在row
参数中添加类型注释即可。在这种情况下,您的类型为CsvFile.Row
,并且由于CsvFile.Row具有Id属性,因此我们可以在函数中访问它。现在这个函数返回一个布尔值。你也可以让它返回实际的行。
let nullid (row: CsvFile.Row) =
row.Id = 15
let otherid (row: CsvFile.Row) =
row.Id = 40
然后剩下的就是在Seq.filter
中应用它并否定它:
let iddata =
data
|> Seq.filter (not << nullid)
|> Seq.filter (not << otherid)
|> Seq.toList
//val iddata : CsvProvider<...>.Row list = [(48, "MO"); (78, "TN"); (41, "VT")]