尝试过滤掉不在另一个序列中的序列中的值

San*_*aus 1 f#

我试图从序列中过滤掉不在另一个序列中的值.我很确定我的代码是有效的,但是在我的计算机上运行需要很长时间,因此我不确定,所以我在这里看看社区的想法.

代码如下:

let statezip =
    StateCsv.GetSample().Rows
    |> Seq.map (fun row -> row.State)
    |> Seq.distinct

type State = State of string

let unwrapstate (State s) = s
let neededstates (row:StateCsv) = Seq.contains (unwrapstate row.State) statezip
Run Code Online (Sandbox Code Playgroud)

我正在通过requiredstates函数进行过滤.我这样做的方式有问题吗?

let datafilter =
    StateCsv1.GetSample().Rows
    |> Seq.map (fun row -> row.State,row.Income,row.Family)
    |> Seq.filter neededstates
    |> List.ofSeq
Run Code Online (Sandbox Code Playgroud)

我相信它应该用真值来过滤序列,因为requiredstates函数是一个bool.StateCsv和StateCsv1具有相同的确切结构,但来自不同年份.

Aar*_*ach 5

contains对序列和列表的评估可能很慢.对于要检查集合中是否存在元素的情况,F#Set类型是理想的.您可以使用序列将序列转换为集合Set.ofSeq,然后在集合上运行逻辑.以下示例使用1到10000之间的数字,然后使用序列和集合通过检查值不在偶数集合中来将结果过滤为仅奇数.

使用序列:

let numberSeq = {0..10000}
let evenNumberSeq = seq { for n in numberSeq do if (n % 2 = 0) then yield n }

#time
numberSeq |> Seq.filter (fun n -> evenNumberSeq |> Seq.contains n |> not) |> Seq.toList
#time
Run Code Online (Sandbox Code Playgroud)

这对我来说大约需要1.9秒.

使用集合:

let numberSet = numberSeq |> Set.ofSeq
let evenNumberSet = evenNumberSeq |> Set.ofSeq

#time
numberSet |> Set.filter (fun n -> evenNumberSet |> Set.contains n |> not)
#time
Run Code Online (Sandbox Code Playgroud)

这仅运行0.005秒.希望您可以在执行contains操作之前实现序列设置,从而获得此级别的加速.