我正在尝试确定如何在Reactive Extensions中使用group by功能。有人有一个简单的例子来说明它在F#中使用吗?
谢谢!
答案 0 :(得分:4)
你最有可能面临的问题是,当与Func<T, T1...>
,Action<T>
等相关时,F#的类型推断对于lambdas来说很难,特别是在具有多次重载的方法中。
如果您正在使用专为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)