如何将 IGroupedObservable 转换为 IGrouping? [英] How to convert an IGroupedObservable to IGrouping?

查看:26
本文介绍了如何将 IGroupedObservable 转换为 IGrouping?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可观察的元素序列,这些元素具有 char Key 属性,其值范围从 'A''E'.我想根据这个键对这些元素进行分组.对它们进行分组后,我希望通过一组可观察到的结果来显示结果,以便我可以分别处理每个组.我的问题是我找不到一种很好的方法来保存最终可观察对象中每个组的键.这是我正在尝试做的一个例子:

I have an observable sequence of elements that have a char Key property, that has values in the range from 'A' to 'E'. I want to group these elements based on this key. After grouping them I want the result to by an observable of groups, so that I can process each group separately. My problem is that I can't find a nice way to preserve the key of each group in the final observable. Here is an example of what I am trying to do:

var observable = Observable
    .Interval(TimeSpan.FromMilliseconds(100))
    .Take(42)
    .GroupBy(n => (char)(65 + n % 5))
    .Select(grouped => grouped.ToArray())
    .Merge();

observable.Subscribe(group =>
    Console.WriteLine($"Group: {String.Join(", ", group)}"));

输出:

Group: 0, 5, 10, 15, 20, 25, 30, 35, 40
Group: 1, 6, 11, 16, 21, 26, 31, 36, 41
Group: 2, 7, 12, 17, 22, 27, 32, 37
Group: 3, 8, 13, 18, 23, 28, 33, 38
Group: 4, 9, 14, 19, 24, 29, 34, 39

组正确,但键 ('A' - 'E') 丢失.observable 的类型是 IObservable.我想要它做什么取而代之的是 IObservable>.这样 group.Key 将在最终订阅代码中可用.但据我所知没有内置的方法来转换 IGroupedObservable(GroupBy 运算符)到 IGrouping.我可以看到运算符 ToArrayToListToLookupToDictionary 等,但不是 ToGrouping 运算符.我的问题是,我该如何实现这个运算符?

The groups are correct, but the keys ('A' - 'E') are lost. The type of the observable is IObservable<long[]>. What I would like it to be instead, is an IObservable<IGrouping<char, long>>. This way the group.Key would be available inside the final subscription code. But as far as I can see there is no built-in way to convert an IGroupedObservable (the result of the GroupBy operator) to an IGrouping. I can see the operators ToArray, ToList, ToLookup, ToDictionary etc, but not a ToGrouping operator. My question is, how can I implement this operator?

这是我实现它的不完整尝试:

Here is my incomplete attempt to implement it:

public static IObservable<IGrouping<TKey, TSource>> ToGrouping<TKey, TSource>(
    this IGroupedObservable<TKey, TSource> source)
{
    return Observable.Create<IGrouping<TKey, TSource>>(observer =>
    {
        // What to do?
        return source.Subscribe();
    });
}

我的意图是在原始示例中使用它而不是 ToArray,如下所示:

My intention is to use it in the original example instead of the ToArray, like this:

.Select(grouped => grouped.ToGrouping())

推荐答案

这可以满足您的大部分需求:

This does most of what you want:

var observable = Observable
    .Interval(TimeSpan.FromMilliseconds(100))
    .Take(42)
    .GroupBy(n => (char)(65 + n % 5))
    .SelectMany(grouped => grouped.ToArray().Select(a => (key: grouped.Key, results: a)));

这是一个 IObservable.如果您想要 IGrouping 接口,则必须创建一个对象,因为我认为没有可用的对象:

That's an IObservable<ValueTuple<TKey, TResult[]>. If you wanted the IGrouping interface, you would have to make an object, since I don't think there's one available for you:

public static class Grouping
{
    // Because I'm too lazy to code types
    public static Grouping<TKey, TResult> Create<TKey, TResult>(TKey key, IEnumerable<TResult> results)
    {
        return new Grouping<TKey, TResult>(key, results);
    }
}

public class Grouping<TKey, TResult> : IGrouping<TKey, TResult>
{
    public Grouping(TKey key, IEnumerable<TResult> results)
    {
        this.Key = key;
        this.Results = results;
    }
    
    public TKey Key { get; }
    public IEnumerable<TResult> Results { get; }

    public IEnumerator<TResult> GetEnumerator()
    {
        return Results.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return Results.GetEnumerator();
    }
}

那么你的 observable 就变成了:

then your observable becomes:

var o2 = Observable.Interval(TimeSpan.FromMilliseconds(100))
    .Take(42)
    .GroupBy(n => (char)(65 + n % 5))
    .SelectMany(grouped => grouped.ToArray().Select(a => Grouping.Create(grouped.Key, a)));

这篇关于如何将 IGroupedObservable 转换为 IGrouping?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆