我有一个可观察的序列IObservable<int>
,我希望将其转换为IObservable<IList<int>>
,同时保留以下要求:
我可以使用Buffer
运算符轻松生成一种批次,但我不知道如何在同一数据上生成两批。
修改
这是一个简单的代码,只生成一种批处理。
IObservable<int> source = GetSource(...);
await source
.Buffer(1000)
.Select(batch => Observable.FromAsync(() => ProcessBatchAsync(batch)))
.Merge(MaxConcurrentBatches)
.DefaultIfEmpty();
...
private async Task<Unit> ProcessBatchAsync(IList<int> batch)
{
...
return Unit.Default;
}
我想要的是:
EDIT2
我需要详细说明约束。原始observable位于SqlReader
对象的顶部,订阅它两次意味着读者创建两次并且数据库访问加倍。我只需要一个订阅。
EDIT3
对于示例数据,我们可以使用Observable.Range(0,10000)
。鉴于该序列,我需要按任何顺序进行以下批处理:
[0..1000), [0..400), [1000..2000),[400..800),[2000..3000),[800..1200),[3000..4000),[1200..1600) ... [9000..10000) ... [9600..10000)
或者您可以使用范围为[0..100]的批次为10和4的数字。这并不重要,因为解决方案不应取决于批量大小,也不取决于批次类型的数量。
例如,它应适用于3批10,4和6号。或任何其他组合。
EDIT4
我认为我把人与我的约束混为一谈。当我说“交错”时,我并不是说批次类型必须严格旋转。这正是我试图解释必须同时生产批次的不同类型。给定3个批次类型A,B和C,有可能偶尔一个接一个地生产两批A型。然而,如果首先是A类的所有批次,然后是B类的所有批次,然后是所有C类批次,那是不可接受的。
答案 0 :(得分:2)
我认为这会产生你需要的东西:
var query =
Observable
.Range(0, 10000)
.Publish(ns =>
ns
.Buffer(1000)
.Concat(Observable.Repeat(new List<int>() as IList<int>))
.Zip(ns.Buffer(400), (n1s, n2s) => new [] { n1s, n2s })
.SelectMany(nns => nns)
.Where(xs => xs.Any()));
根据您的示例输出正确交错。
如果我将数字减少100倍,那么我得到这个输出:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9 0, 1, 2, 3 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 4, 5, 6, 7 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 8, 9, 10, 11 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 12, 13, 14, 15 40, 41, 42, 43, 44, 45, 46, 47, 48, 49 16, 17, 18, 19 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 20, 21, 22, 23 60, 61, 62, 63, 64, 65, 66, 67, 68, 69 24, 25, 26, 27 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 28, 29, 30, 31 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 32, 33, 34, 35 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 36, 37, 38, 39 40, 41, 42, 43 44, 45, 46, 47 48, 49, 50, 51 52, 53, 54, 55 56, 57, 58, 59 60, 61, 62, 63 64, 65, 66, 67 68, 69, 70, 71 72, 73, 74, 75 76, 77, 78, 79 80, 81, 82, 83 84, 85, 86, 87 88, 89, 90, 91 92, 93, 94, 95 96, 97, 98, 99
如果你不需要它们严格交错,那么这是一种推广n
缓冲区的方法:
var buffers = new [] { 1000, 400, 500, 300 };
var source = Observable.Range(0, 10000);
var result = source.Publish(ss => buffers.Select(b => ss.Buffer(b)).Merge());
答案 1 :(得分:0)
以下方法如何
var observable = Observable.Range(0, 10000);
Task.Run(() => observable.Buffer(400).Subscribe(buffer => /* process buffer */ ));
Task.Run(() => observable.Buffer(1000).Subscribe(buffer => /* process buffer */ ));
将同时生产两种批次。
答案 2 :(得分:0)
此代码创建两个IObservable<IList<int>>
序列。
var source = Observable.Range(0,10000)
.Publish();
var batchesOf1000 = source.Buffer(1000);
var batchesOf400 = source.Buffer(400);
batchesOf1000.Subscribe(batch => batch.Dump());
batchesOf400.Subscribe(batch => batch.Dump());
var disposable = source.Connect();