【发布时间】:2019-12-05 14:01:04
【问题描述】:
我观察到一个反应流Observable<Event>,目前它直接发出它的事件。基于 BEGIN/END 事件,我想在内部组的支持下对这个事件流进行分组。
输入流
我有如下事件流:
Event(type = Data, groupId = 1)
Event(type = BeginGroup, groupId = 2) // outer group begins
Event(type = Data, groupId = 2)
Event(type = BeginGroup, groupId = 3) // inner group begins
Event(type = Data, groupId = 3)
Event(type = EndGroup, groupId = 3) // inner group ends
Event(type = EndGroup, groupId = 2) // outer group ends
Event(type = Data, groupId = 4)
Event(type = Data, groupId = 5)
编辑 - 附加前提条件:
我在示例数据中添加了 ID,但通常我不需要 ID。流将注意满足以下要求:
- 每个
BeginGroup事件都会在某个时间跟随相应的EndGroup事件 - 组内的事件(在我的示例中具有相同的组理念)将始终在流内的开始/结束事件内,因此可以保证顺序(如上例中)李>
期望的输出流
所以我确保每个事件要么是它上面的组的一部分,要么如果它不是真实组的一部分,则具有唯一的 ID。我想将上述 9 个事件流分组为以下 4 个事件流:
Event(type = Data, groupId = 1)
GroupEvent(groupId = 2, data = <LIST of Events and/or sub groups>) with following data:
data = [
Event(type = BeginGroup, groupId = 2)
Event(type = Data, groupId = 2)
GroupEvent(groupId = 3, data = <LIST of Events and/or sub groups>) with following data:
data = [
Event(type = BeginGroup, groupId = 3)
Event(type = Data, groupId = 3)
Event(type = EndGroup, groupId = 3)
]
Event(type = EndGroup, groupId = 2)
]
Event(type = Data, groupId = 4)
Event(type = Data, groupId = 5)
我想要什么 - 逻辑
我想在BeginGroup 类型的事件发生后立即开始分组,直到发生正确的EndGroup 事件,并将这两个事件之间的所有事件(包括最终嵌套的组事件)分组。开始/结束组事件之外的元素仅作为单个事件传递。
这是我目前尝试的方法
在问这个问题之前我尝试了一些东西,但我来自 java,我什至很少使用窗口/缓冲区操作符,而且对它们的经验也很少。我看到 C# 中有类似 GroupByUntil 的操作符,所以我尝试使用它,但在我的示例中它从不发出任何内容。
var eventObservable: Observable<Event> = ...
// 1) make the observable hot so it can be resued inside the groupbyuntil operator
eventObservable = observable.Publish().RefCount();
var res = eventObservable
.GroupByUntil(
e => e.GroupId, // selector for groups => the group id can be used here
grp => eventObservable.Where(e => e.GroupId != grp.Key) // stop a group as soon as the group id changes
)
.SelectMany(data => data.ToList()) // flatten the observable
.Select(data => {
// Convert the list of Events to GroupEvent if it contains more than 1 event
var list = data.ToList();
if (list.Count == 1)
return list[0];
return new GroupEvent(list);
})
这种方法不起作用,它根本不会发出任何东西(eventObservable 确实会正确发出它的项目)。此外,它缺少对嵌套组的支持(理论上是否可行)。
有人可以向我解释如何解决我的问题吗?
【问题讨论】:
-
您想完全基于顺序/嵌套进行分组吗?还是按组ID?如果 ID 不同步或不有序怎么办?
-
实际上,group id 是不相关的,甚至可能没有必要,事件的顺序可以被认为是理所当然的,是分组的来源。所以我想实际上按顺序分组并根据事件(关于内部组)开始组/结束组 - 在最后我的第一个标题下将此信息添加到我的问题中(实际上,在我的测试中,我什至手动添加了 GroupId在
Buffer(2, 1)的帮助下,手动生成了 id,然后再次将流展平......)
标签: c# system.reactive reactive