我正在尝试确定如何在 Reactive Extensions 中使用 group by 功能。是否有人有一个简单的例子来说明它在 F# 中的使用?
谢谢!
Func<T, T1...>
您最有可能面临的问题是,当与 等相关时,F# 的类型推断很难用于 lambda Action<T>
,尤其是在具有多个重载的方法中。
如果您使用的是为惯用的 C#/VB 设计的 Rx API,大多数情况下您最终将不得不注释类型以将编译器指向正确的方向。
GroupBy 以最简单的形式接受一个键选择器并产生一个可观察的组。每个组都有一个键,它本身就是一个 Observable,它是该键下的值流。
在此示例中,我们形成了两个组:偶数或奇数,因此您得到两个IGroupedObservable<string, int>
并SelectMany
用于重新组合组。
使用常规的 Rx 方法:
let log message s = printfn "%s: %A" message s
let disposable =
Observable.Interval(TimeSpan.FromSeconds(0.5))
.Select(int)
.Do(log "Produced")
.GroupBy(fun n -> if n % 2 = 0 then "Even" else "Odd")
.SelectMany(fun (group : IGroupedObservable<string, int>) -> group.Select(fun i -> group.Key, i))
.Do(log "Kind")
.Subscribe()
这是非常可怕的......
为了使它更惯用,你需要像这样扩充 Observable 模块:
type Observable with
static member log message o = Observable.Do(o, log message)
static member groupBy selector o = Observable.GroupBy(o, (fun v -> selector(v)))
static member collect (selector : 'a -> IObservable<'b>) o = Observable.SelectMany(o, selector)
现在您可以将上面相同的代码表示为:
let disposable =
Observable.Interval(TimeSpan.FromSeconds(0.5))
|> Observable.map int
|> Observable.log "Produced"
|> Observable.groupBy (fun n -> if n % 2 = 0 then "Even" else "Odd")
|> Observable.collect(fun group -> group |> Observable.map(fun i -> group.Key, i))
|> Observable.log "Kind"
|> Observable.subscribe(fun _ -> ())
...更具可读性,不需要注释。
输出:
Produced: 0
Kind: ("Even", 0)
Produced: 1
Kind: ("Odd", 1)
Produced: 2
Kind: ("Even", 2)
Produced: 3
Kind: ("Odd", 3)