F# 当值(某物的id)发生变化时,及时写入记录
当某物的id值发生变化时,如何及时写入记录?对于某些列表,当true->false和false->true时每个记录的id 例如表F# 当值(某物的id)发生变化时,及时写入记录,f#,F#,当某物的id值发生变化时,如何及时写入记录?对于某些列表,当true->false和false->true时每个记录的id 例如表 id value 1 0 2 0 2 0 2 0 1 0 2 1 --> the only changes here 2 1 1 0 2 0 --> and here (node with id 2 changed 1 -> 0 ) 1 1 --> node with id 1 changed 0 -> 1
id value
1 0
2 0
2 0
2 0
1 0
2 1 --> the only changes here
2 1
1 0
2 0 --> and here (node with id 2 changed 1 -> 0 )
1 1 --> node with id 1 changed 0 -> 1
结果表
2 1
2 0
1 1
我的想法不是功能性的,有点奇怪,我正在考虑功能性的或linq的方法来实现同样的想法
let oop = ref (filteredsq
|> Seq.distinctBy(fun (node,v,k) -> k)
|> Seq.map(fun (node,v,k) -> k, false )
|> Array.ofSeq )
[for (node,value,key) in filteredsq do
let i = ref 0
for (k,v) in !oop do
if key = k && value <> v then
(!oop).[!i] <- (k,value)
yield node
i := !i + 1 ]
让oop=ref(filteredsq
|>顺序区分(乐趣(节点,v,k)->k)
|>序列映射(fun(节点,v,k)->k,false)
|>数组(0.1)
[对于filteredsq do中的(节点、值、键)]
设i=ref0
对于(k,v)in!oop do
如果key=k&&v值,则
(!oop)。[!i]我会做类似的事情
List
|> List.toSeq
|> Seq.pairwise
|> Seq.pick (fun ((fa,fb),(sa,sb)) -> if fb <> sb then Some(sa,sb) else None)
列表
|>List.toSeq
|>顺序:成对
|>Seq.pick(fun((fa,fb),(sa,sb))->如果是fb sb,那么一些(sa,sb)其他无)
我会做类似的事情
List
|> List.toSeq
|> Seq.pairwise
|> Seq.pick (fun ((fa,fb),(sa,sb)) -> if fb <> sb then Some(sa,sb) else None)
列表
|>List.toSeq
|>顺序:成对
|>Seq.pick(fun((fa,fb),(sa,sb))->如果是fb sb,那么一些(sa,sb)其他无)
已更新
open System.Collections.Generic
let filter (acc:'a) (f:('a -> 'b -> bool * 'a)) (s:'b seq) =
let rec iter (acc:'a) (e:IEnumerator<'b>) =
match e.MoveNext() with
| false -> Seq.empty
| true -> match f acc e.Current with
| (true,newAcc) -> seq { yield e.Current; yield! iter newAcc e}
| (false,newAcc) -> seq { yield! iter newAcc e}
iter acc (s.GetEnumerator())
let skipUntilChange (f : 'a -> 'b) (s : 'a seq) =
s |> Seq.skip 1
|> filter (s |> Seq.head |> f)
(fun a b -> if a = f b then false,f b else true,f b)
[(1,0);(2,0);(2,0);(2,0);(1,0);(2,1);(2,1);(1,0);(2,0);]
|> Seq.mapi (fun c (i,v) -> (i,v,c))
|> Seq.groupBy (fun (i,v,c) -> i)
|> Seq.map (snd >> skipUntilChange (fun (_,v,_) -> v))
|> Seq.concat |> Seq.sortBy (fun (i,v,c) -> c)
|> Seq.map (fun (i,v,c) -> (i,v))
|> printfn "%A"
open System.Collections.Generic
let过滤器(acc:'a)(f:('a->'b->bool*'a))(s:'b seq)=
让我们记录(附件a)(e:IEnumerator'b)(s:'a seq)=
s |>序号1
|>过滤器(s |>序列头|>f)
(乐趣a b->如果a=f b则为假,否则为真,f b)
[(1,0);(2,0);(2,0);(2,0);(1,0);(2,1);(2,1);(1,0);(2,0);]
|>Seq.mapi(趣味c(i,v)->(i,v,c))
|>Seq.groupBy(乐趣(i、v、c)->i)
|>Seq.map(snd>>skipUntilChange(乐趣(u,v,u)->v))
|>序号concat |>序号sortBy(乐趣(i、v、c)->c)
|>序列图(乐趣(i,v,c)->(i,v))
|>printfn“%A”
已更新
open System.Collections.Generic
let filter (acc:'a) (f:('a -> 'b -> bool * 'a)) (s:'b seq) =
let rec iter (acc:'a) (e:IEnumerator<'b>) =
match e.MoveNext() with
| false -> Seq.empty
| true -> match f acc e.Current with
| (true,newAcc) -> seq { yield e.Current; yield! iter newAcc e}
| (false,newAcc) -> seq { yield! iter newAcc e}
iter acc (s.GetEnumerator())
let skipUntilChange (f : 'a -> 'b) (s : 'a seq) =
s |> Seq.skip 1
|> filter (s |> Seq.head |> f)
(fun a b -> if a = f b then false,f b else true,f b)
[(1,0);(2,0);(2,0);(2,0);(1,0);(2,1);(2,1);(1,0);(2,0);]
|> Seq.mapi (fun c (i,v) -> (i,v,c))
|> Seq.groupBy (fun (i,v,c) -> i)
|> Seq.map (snd >> skipUntilChange (fun (_,v,_) -> v))
|> Seq.concat |> Seq.sortBy (fun (i,v,c) -> c)
|> Seq.map (fun (i,v,c) -> (i,v))
|> printfn "%A"
open System.Collections.Generic
let过滤器(acc:'a)(f:('a->'b->bool*'a))(s:'b seq)=
让我们记录(附件a)(e:IEnumerator'b)(s:'a seq)=
s |>序号1
|>过滤器(s |>序列头|>f)
(乐趣a b->如果a=f b则为假,否则为真,f b)
[(1,0);(2,0);(2,0);(2,0);(1,0);(2,1);(2,1);(1,0);(2,0);]
|>Seq.mapi(趣味c(i,v)->(i,v,c))
|>Seq.groupBy(乐趣(i、v、c)->i)
|>Seq.map(snd>>skipUntilChange(乐趣(u,v,u)->v))
|>序号concat |>序号sortBy(乐趣(i、v、c)->c)
|>序列图(乐趣(i,v,c)->(i,v))
|>printfn“%A”
我不确定是否完全理解您的问题,但以下内容根据您的示例给出了正确的输出。我们的想法是首先过滤掉没有正确键的值,然后使用Seq.pairwaise
(如jpalmer的解决方案)查找值更改的位置:
let input = [ (1, 0); (2, 0); (2, 0); (2, 0); (1, 0); (2, 1); (2, 1); (1, 0); (2, 0) ]
let findValueChanges key input =
input
|> Seq.filter (fun (k, v) -> k = key) // Get values with the right key
|> Seq.pairwise // Make tuples with previous & next value
|> Seq.filter (fun ((_, prev), (_, next)) -> prev <> next) // Find changing points
|> Seq.map snd // Return the new key-value pair (after change)
(对于您的输入,键1的值没有变化,因为该值始终是1,0
)我不确定是否完全理解您的问题,但下面根据您的示例给出了正确的输出。我们的想法是先过滤掉没有正确键的值,然后使用Seq.pairwaise
(如jpalmer的解决方案中所述)查找值变化的位置:
let input = [ (1, 0); (2, 0); (2, 0); (2, 0); (1, 0); (2, 1); (2, 1); (1, 0); (2, 0) ]
let findValueChanges key input =
input
|> Seq.filter (fun (k, v) -> k = key) // Get values with the right key
|> Seq.pairwise // Make tuples with previous & next value
|> Seq.filter (fun ((_, prev), (_, next)) -> prev <> next) // Find changing points
|> Seq.map snd // Return the new key-value pair (after change)
(对于您的输入,键1的值没有变化,因为值总是1,0
)我认为如果您定义如下函数:
let getChanges f items =
items
|> Seq.map (fun x -> f x, x)
|> Seq.pairwise
|> Seq.choose (fun ((a, _), (b, x)) -> if a <> b then Some x else None)
我认为如果你定义一个如下的函数:
let getChanges f items =
items
|> Seq.map (fun x -> f x, x)
|> Seq.pairwise
|> Seq.choose (fun ((a, _), (b, x)) -> if a <> b then Some x else None)
我只需要使用一个内部可变字典来跟踪每个键最后看到的值,并在任何值与该键上的最后一个值不同时生成(键,值):
let filterChanges (s:('a*'b) seq) =
let dict = new System.Collections.Generic.Dictionary<'a,'b>()
seq {
for (key,value) in s do
match dict.TryGetValue(key) with
| false,_ -> dict.[key] <- value
| true,lastValue ->
if lastValue <> value then
yield (key,value)
dict.[key] <- value
}
让过滤器更改(s:('a*'b)顺序)=
让dict=new System.Collections.Generic.Dictionary()
序号{
对于s do中的(键、值)
将dict.TryGetValue(键)与
|false,->dict[键]
如果lastValue,则
收益率(键、值)
dict.[key]过滤器更改[(1,0);(2,0);(2,0);(1,0);(2,1);(2,1);(1,0);(2,0);(1,1)];;
valit:seq=seq[(2,1);(2,0);(1,1)]
我只需要使用一个内部可变字典来跟踪每个键最后看到的值,并在任何值与该键上的最后一个值不同时产生(键,值):
let filterChanges (s:('a*'b) seq) =
let dict = new System.Collections.Generic.Dictionary<'a,'b>()
seq {
for (key,value) in s do
match dict.TryGetValue(key) with
| false,_ -> dict.[key] <- value
| true,lastValue ->
if lastValue <> value then
yield (key,value)
dict.[key] <- value
}
让过滤器更改(s:('a*'b)顺序)=
让dict=new System.Collections.Generic.Dictionary()
序号{
对于s do中的(键、值)
将dict.TryGetValue(键)与
|false,->dict[键]
如果lastValue,则
收益率(键、值)
dict.[key]过滤器更改[(1,0);(2,0);(2,0);(1,0);(2,1);(2,1);(1,0);(2,0);(1,1)];;
valit:seq=seq[(2,1);(2,0);(1,1)]
谢谢,但我只需要比较相同id的值。检查示例表。2 1;1 0;2 0-这里我不注册2.1->1.0,我注册2.1->2.0。谢谢,但我只需要比较相同id的值。检查示例表。2 1;1 0;2 0-这里我不注册2.1->1.0,我注册2.1->2.0。谢谢。我需要一些时间来帮助您理解:)毕竟,存在一些错误:错误3非泛型类型“System.Collections.IEnumerator”不需要任何类型参数,但这里给出了1个类型参数@nCdy:您需要打开System.Collections.Generic
。谢谢。我需要一些时间来理解:)毕竟,有一些错误:错误3非泛型类型“System.Collections.IEnumerator”不需要任何类型参数,但这里提供了1个类型参数@nCdy:您需要打开System.Collections.Generic
。感谢您的审阅。您的代码与示例相关:)请阅读问题中的代码以了解想法。我需要处理所有更改(使用任何if(而不仅仅是2))。抱歉,我不太了解你的代码示例。你能扩展你的示例来演示我的答案不能正确处理的情况吗?现在很好(只是我丢失了订单,但这不是什么大问题)谢谢你。[为我自己打开成对:)@nCdy