我有一个“值” IObservable<T>
,它返回T
个元素,这些元素必须按顺序组合成可变长度数组,并且我有一个“控件” IObservable<int>
,它告诉我下一个数组必须多长时间。
删除元素,重复元素或使结果混乱会使结果变得毫无意义。
这是我在Rx.NET中重写的串行连接机器人技术项目。
IObservable<char> values = new [] {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }.ToObservable();
IObservable<int> control = new [] { 1, 4, 2 }.ToObservable();
IObservable<char[]> result = control.SelectMany(length => values.Take(length).ToArray());
我想看到这样的东西:
values ----A--B--C--D--E--F--G--H-->
control --1-----4---------------2--->
result ---[A]---------[BCDE]--[FG]->
但是到目前为止,我的尝试导致了
-[A]-[AB]-[ABCD]->
答案 0 :(得分:1)
好的,这是适合我所有需求的代码。普罗格曼,您在根据您的建议进行这项工作中发挥了作用。在这里,它被包裹在整洁的Observable.Create
中,并变成了IObservable<T>
上的扩展方法,并且使用了一次性方法来处理压缩序列上的预订。
public static IObservable<T[]> Chop<T>(this IObservable<T> values, IObservable<int> control) =>
Observable.Create<T[]>(observer =>
{
List<T> buffer = new List<T>();
return values.Zip(control.SelectMany(length => Enumerable.Repeat(length, length)),
(value, length) => (value, length))
.Subscribe(next =>
{
buffer.Add(next.value);
if (buffer.Count == next.length)
{
observer.OnNext(buffer.ToArray());
buffer.Clear();
}
});
});
示例输出:
values ----A--B--C--D--E--F--G--H--I--J--K--L--M--N--O--P-->
control --1-4-2-0-3-3--------------------------------------->
result ---[A]---------[BCDE]-[FG]----[HIJ]----[KLM]-------->
答案 1 :(得分:0)
您可以创建几个辅助主题,以准备/创建新的可观察对象以构建所需的新可观察对象。您可以为这些可观察对象建立主题:
control
读取的数字。从(1, 4, 2)
您将获得(guid_1, guid_2, guid_2, guid_2, guid_2, guid_3, guid_3)
。将此称为可观察的repeatSize
。Zip()
运算符组合来自repeatSize
和values
的一个值。您将获得以下值的观察值:((A,guid_1), (B,guid_2), (C,guid_2), (D,guid_2), (E,guid_2), (F,guid_3), (G,guid_3))
。将此称为可观察的zippedValues
。zippedValues
并将原始值添加/添加到列表中。还保存来自repeatSize
可观察值的先前值。将其与repeatSize
的当前值进行比较。更改完后(例如从guid_2
更改为guid_3
),您知道您已经到达结束/开始位置,因此可以将填充列表发送到新的可观察对象。之后,您可以重新设置列表,然后再次开始填写。您可能需要构建2-3个Subject<T>
对象,对其进行订阅,并使用多个OnNext()
调用来从其他可观察对象的订阅中填充它们。
答案 2 :(得分:0)
我还没有对此进行测试,但是我相信您可以结合使用Zip()
和Scan()
来产生所需的输出。
IObservable<char> values = new [] {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }.ToObservable();
IObservable<int> control = new [] { 1, 4, 2 }.ToObservable();
IObservable<char[]> result = control.Zip(
control.Scan(values, (rest, length) => rest.Skip(length)),
(length, vals) => vals.Take(length).ToArray()
);