5

假设序列 1 正在网络上检索站点 1、2、3、4、5 的内容(但将以不可预知的顺序返回)。

序列 2 将进入数据库以检索有关这些相同记录 1、2、3、4、5 的上下文(但出于本示例的目的,将以不可预测的顺序返回)。

当每个匹配对在两个序列中都准备好时,是否有一种 Rx 扩展方法可以将它们组合成一个序列?即,如果第一个序列以 4,2,3,5,1 的顺序返回,而第二个序列以 1,4,3,2,5 的顺序返回,则合并后的序列将是 (4,4), (3 ,3), (2,2), (1,1), (5,5) - 一旦每对准备好。我看过 Merge 和 Zip,但它们似乎并不是我想要的。

我不想丢弃不匹配的对,我认为这排除了简单的 .Where.Select 组合。

4

2 回答 2

3
var paired = Observable
    .Merge(aSource, bSource)
    .GroupBy(i => i)
    .SelectMany(g => g.Buffer(2).Take(1));

下面的测试给出了正确的结果。目前它只是采用整数,如果您使用带有键和值的数据,那么您需要按 i.Key 而不是 i 进行分组。

var aSource = new Subject<int>();
var bSource = new Subject<int>();

paired.Subscribe(g => Console.WriteLine("{0}:{1}", g.ElementAt(0), g.ElementAt(1)));

aSource.OnNext(4);
bSource.OnNext(1);
aSource.OnNext(2);
bSource.OnNext(4);
aSource.OnNext(3);
bSource.OnNext(3);
aSource.OnNext(5);
bSource.OnNext(2);
aSource.OnNext(1);
bSource.OnNext(5);

产量:

4:4
3:3
2:2
1:1
5:5

编辑回应布兰登:

对于项目为不同类(AClass和BClass)的情况,可以进行如下调整。

using Pair = Tuple<AClass, BClass>;

var paired = Observable
    .Merge(aSource.Select(a => new Pair(a, null)), bSource.Select(b => new Pair(null, b)))
    .GroupBy(p => p.Item1 != null ? p.Item1.Key : p.Item2.Key)
    .SelectMany(g => g.Buffer(2).Take(1))
    .Select(g => new Pair(
      g.ElementAt(0).Item1 ?? g.ElementAt(1).Item1, 
      g.ElementAt(0).Item2 ?? g.ElementAt(1).Item2));
于 2013-02-25T23:41:22.800 回答
1

所以你有 2 个要配对的可观察序列?

来自Rxx和 GroupBy的配对可以在这里提供帮助。我认为类似于以下的代码可能会做你想要的

var pairs = stream1.Pair(stream2)
       .GroupBy(pair => pair.Switch(source1 => source1.Key, source2 => source2.Key))
       .SelectMany(group => group.Take(2).ToArray()) // each group will have at most 2 results (1 left and 1 right)
       .Select(pair =>
       {
           T1 result1 = default(T1);
           T2 result2 = default(T2);

           foreach (var r in pair)
           {
              if (r.IsLeft) result1 = r.Left;
              else result2 = r.Right;
           }

           return new { result1, result2 };
       });

```

我没有测试过它,也没有添加任何错误处理,但我认为这就是你想要的。

于 2013-02-25T18:21:05.193 回答