【问题标题】:Merging multiple observables into single dictionary将多个可观察对象合并到单个字典中
【发布时间】:2015-01-21 16:59:22
【问题描述】:

我想将多个可观察对象(每个对象返回一个更新对象)组合成一个字典对象。

这是我想要达到的目标的示例:

private IObservable<IDictionary<string, IUpdate>> CreateUpdateStreams(Product product)
{
  var codeObservables = product.Codes.Select(code => CreateUpdateStream(code)).ToList();

  //??? 
  return pointObs.Merge().Select(update => ...);
}


private IObservable<IUpdate> CreateUpdateStream(string code)
{
  ...
  //return an observable of IUpdate
}
  • 我想将所有 IUpdate 合并到一个单独的更新字典中,其中键 = 代码和值 = IUpdate
  • CreateUpdateStreams 的调用者将知道产品,并希望根据更新对每个 Code 对象的某些属性进行更改。例如

产品 = Foo

Product.Codes = {Code1, Code2, Code3}

IDictionary = {Code1, "a"}, {Code2, "b"}, {Code3, "c"}

根据更新的值(在本例中为 a/b/c),将对相应的代码进行不同的更改,例如设置一个属性,如 Code.State = "a" 等。

由于每个 codeObservable 都会以不同的速率更新,Merge 似乎是一个明智的起点。我不确定如何让各个可观察对象的更新更新一个字典对象,该对象保留过去的值。

【问题讨论】:

标签: c# system.reactive


【解决方案1】:

这是您的问题的一个镜头,它利用了匿名类型。它依赖于字典的副作用。请注意,由于 Rx 保证顺序行为,因此不需要在字典上进行同步。

private IObservable<IReadOnlyDictionary<string, IUpdate>> CreateUpdateStreams(Product product)
    {
        var dictionary = new Dictionary<string, IUpdate>();
         return
          product.Codes.Select(
              code => CreateUpdateStream(code).Select(update => new {Update = update, Code = code}))
              .Merge()
              .Do(element => dictionary.Add(element.Code, element.Update))
              .Select(_ => dictionary);
    }

请注意,我已将方法签名更改为返回IObservable&lt;IReadOnlyDictionary&lt;,&gt;&gt;,以防止客户端代码篡改字典。另一种选择是每次都返回字典的新副本。这确保了不可变的行为(但可能会对性能产生影响,具体取决于字典的大小),如下所示:

private IObservable<IDictionary<string, IUpdate>> CreateUpdateStreams(Product product)
    {
        var dictionary = new Dictionary<string, IUpdate>();
        return
            product.Codes.Select(
                code => CreateUpdateStream(code).Select(update => new {Update = update, Code = code}))
                .Merge()
                .Select(element =>
                {
                    dictionary.Add(element.Code, element.Update);
                    return new Dictionary<string, IUpdate>(dictionary);
                });
    }

【讨论】:

  • Scan(new Dictionary(), (dict, e) =&gt; { dict.Add(e.Code, e.Update); return dict; }) 替换您的本地dictionary 变量和DoSelect。此外,如果不变性很重要,请使用 ImmutableDictionary
猜你喜欢
  • 1970-01-01
  • 2017-09-22
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-17
相关资源
最近更新 更多