我正在尝试拉链' Rx中的任意数量的流,其中元素对应但可以不按顺序处理。每个流的元素都有一个标识符,可用于将它们匹配在一起。例如。元素看起来像:
public class Element
{
public string Key {get; set;}
}
通常,zip只会根据其出现次数组合元素:
|-A-----------A
|--B---------B-
|-----C------C-
|-----ABC-----ABC <- zip
但是,如果我们只想匹配共享相同Key的元素呢?我正在寻找一个更像这样的序列:
(在此示例中,键为1或2)
|--2A-------1A----------
|----1B----------2B-----
|------1C-----------2C--
|-----------1ABC----2ABC <- zipped by key 1 & 2 respectively
我觉得GroupJoin适合这种情况,但它只服务于两个Observable并且链接它们很快失控。
我也看了And / Then / When但是并没有真正理解如何为这种情况构建它。
理想情况下,我想要一个我可以调用并提供结果选择器的扩展方法,其中结果选择器的输入保证具有相同的键。
你会如何解决这个问题?
答案 0 :(得分:0)
这是我在LinqPad中碰到的东西。它符合您对大理石图的要求。然而,它比我想要的更加混乱。
Nuget依赖Rx-Testing
void Main()
{
TestScheduler scheduler = new TestScheduler();
/*
|--2A-------1A----------
|----1B----------2B-----
|------1C-----------2C--
|-----------1ABC----2ABC <- zipped by key 1 & 2 respectively
*/
var sourceA = scheduler.CreateColdObservable(
ReactiveTest.OnNext(3, "2A"),
ReactiveTest.OnNext(12, "1A"));
var sourceB = scheduler.CreateColdObservable(
ReactiveTest.OnNext(5, "1B"),
ReactiveTest.OnNext(17, "2B"));
var sourceC= scheduler.CreateColdObservable(
ReactiveTest.OnNext(7, "1C"),
ReactiveTest.OnNext(20, "2C"));
var observer = scheduler.CreateObserver<string>();
var query = Observable.Merge(sourceA, sourceB, sourceC)
.GroupBy(x => GetKey(x))
.SelectMany(grp => grp.Select(x=>GetValue(x))
.Take(3)
.Aggregate(new List<string>(),
(accumulator, current) => {
accumulator.Add(current);
return accumulator;
})
.Select(acc=>CreateGroupResult(grp.Key, acc)));
query.Subscribe(observer);
scheduler.Start();
ReactiveAssert.AreElementsEqual(
new[]{
ReactiveTest.OnNext(12, "1ABC"),
ReactiveTest.OnNext(20, "2ABC")
},
observer.Messages
);
}
// Define other methods and classes here
private static string CreateGroupResult(string key, IEnumerable<string> values)
{
var combinedOrderedValues = string.Join(string.Empty, values.OrderBy(v => v));
return string.Format("{0}{1}", key, combinedOrderedValues);
}
private static string GetKey(string message)
{
return message.Substring(0, 1);
}
private static string GetValue(string message)
{
return message.Substring(1);
}