RX主题,分组/相关,直到满足条件

时间:2017-03-22 21:22:56

标签: c# system.reactive

我有一个项目流,我想创建一个按属性分组的订阅,直到满足条件。

例如,假设我想按名称对EventItem进行分组,直到观察到特定的Id为止。这一点的关键是将事件关联起来,直到我们看到一个特定的Id,表示不再有相关事件。然后我想对每组相关事件执行一些操作。

public class EventItem
{
  public int Id { get; set }
  public string Name { get; set; }
}

// Using a Subject since it seems the simplest way
Subject<EventItem> eventStream;
...

// A seperate thread pushes EventItem objects into the Subject
eventStream.OnNext(eventItem);

// Struggling here...
IDisposable subscription = eventStream.????

我尝试了几种与GroupByGroupByUntilTakeUntilTakeWhile等的组合,但我无法弄清楚如何做到这一点(我是对Rx缺乏经验)

2 个答案:

答案 0 :(得分:2)

我知道已有一个已接受的答案,但似乎过于复杂。在@Enigmativity的评论中工作:

var subscription = eventStream
    .GroupBy(x => x.Name)
    .Select(o => o.TakeWhile(ei => ei.Id != 42))
    .SelectMany(o => o.ToList()) //If you want y to be IList<EventItem>, use this line. If you prefer y to be IObservable<EventItem>, comment out.
    .Subscribe(y => {});

答案 1 :(得分:1)

修改

基于@Shlomo的回答以及OP关于希望它不能完成的评论

var subscription = producer
        .TakeWhile(ei => ei.Id != 42)
        .GroupBy(x => x.Name)
        .Select(o => o)
        .SelectMany(o => o.ToList()) //If you want y to be IList<EventItem>, use this line. If you prefer y to be IObservable<EventItem>, comment out.
        .Repeat()
        .Subscribe();

原始答案

这有用吗?

        Subject<Notification> producer = new Subject<Notification>();

        //This way there's only one producer feeding the group and the duration
        var connectedProducer =
            producer
                .Publish()
                .RefCount();

        connectedProducer
            .GroupByUntil(
                item => item.Name,
                item => connectedProducer.Where(x=> x.Id == 3))
            .SelectMany(result =>
            {
                return result.Aggregate<Notification, List<Notification>>(new List<Notification>(), (dict, item) =>
                {
                    dict.Add(item);
                    return dict;
                });
            })
            //not sure if you need this but just a way to filter out the signal
            .Where(item => item.First().Id != 3) 
            .Subscribe(results =>
            {
                //This will only run after a "3" is passed in and then you get a list of everything passed in with the names
                //not sure if you wanted intermediate results or for it all to just come through once the signal indicates processing
            });

我的基础是我之前的答案,并稍作修改。 Rx grouped throttling