编辑:在09/15/2013-我正在描述我的情况,进一步分解为可帮助大家更好地了解我的情况的步骤。也添加了整个应用程序的源代码以供下载。如果要跳到原始问题,请向下滚动到最后一个标题。请让我知道问题。谢谢
概括
阿拉斯加州首府朱诺市有一个AST(阿拉斯加州州骑兵)总部大楼,他们希望在这里显示一个大屏幕,上面显示一个数字并自动更新。该数字称为(犯罪商指数)或CQI
CQI基本上是一个计算得出的数字,用以显示该州的当前犯罪情况。
它是如何计算的?
运行该屏幕的程序是一个.NET WPF应用程序,该应用程序通过IObservable热流不断接收CrimeReport对象。
计算每个城市的CQI,然后取所有城市的Sum(),称为州CQI
这是计算状态CQI的步骤
步骤1-接收犯罪数据
每次报告犯罪时,都会将CrimeReport发送到.NET应用程序。它具有以下组成部分
犯罪日期
市-市/县
严重级别-严重/严重
EstimatedSolveTime-AST确定解决犯罪所需的估计天数。
因此,在这一步中,我们订阅IObservable并创建MainViewModel实例
IObservable<CrimeReport> reportSource = mainSource.Publish();
MainVM = new MainViewModel(reportSource);
reportSource.Connect();
第2步-按城市分组并按城市进行数学运算
收到报告后,请按城市将其分组
var cities = reportSource.GroupBy(k => k.City)
.Select(g => new CityDto(g.Key, g);
CityDto是DTO类,它获取当前城市的所有报告并计算城市的CQI。
通过以下公式计算城市的CQI
这是CityDto的类定义
internal class CityDto
{
public string CityName { get; set; }
public IObservable<decimal> CityCqi {get; set;}
public CityDto(string cityName, IObservable<CrimeReport> cityReports)
{
CityName = cityName;
// Get all serious and non serious crimes
//
var totalSeriousCrimes = cityReports.Where(c => c.Severity == CrimeSeverity.Serious)
.Scan(0, (p, _) => p++);
var totalnonSeriousCrimes = cityReports.Where(c => c.Severity == CrimeSeverity.NonSerious)
.Scan(0, (p, _) => p++);
// Get the ratio
//
var ratio = Observable.CombineLatest(totalSeriousCrimes, totalnonSeriousCrimes,
(s, n) => n == 0? s : s/n); // Avoding DivideByZero here
// Get the minimum and maximum estimated solve time
//
var minEstimatedSolveTime = cityReports.Select(c => c.EstimatedSolveTime)
.Scan(5000, (p, n) => n < p? n : p);
var maxEstimatedSolveTime = cityReports.Select(c=>c.EstimatedSolveTime)
.Scan(0, (p, n) => n > p? n : p);
//Time for the City's CQI
//
CityCqi = Observable.CombineLatest(ratio, minEstimatedSolveTime, maxEstimatedSolveTime, (r, n, x) => r < 1.0? r * n : r * m);
}
}
现在我们有了City DTO对象,可以维护City的CQI值并通过IObservable公开实时的CQI,阿拉斯加州首府想将所有城市的CQI求和(显示)为阿拉斯加的CQI并在屏幕上实时显示,每个在参与CQI计划的市/县中任何地方报告的犯罪应立即对该州的CQI产生影响
第3步-汇总城市的状态数据
现在我们要计算在大屏幕上实时更新的整个州的CQI,我们有一个称为MainViewModel的州 View 模型
internal class MainViewModel
{
public MainViewModel(IObservable<CrimeReport> mainReport)
{
/// Here is the snippet also mentioned in Step 2
//
var cities = mainReport.GroupBy(k => k.City)
.Select(g => new CityDto(g.Key, g));
///// T h i s ///// Is //// Where //// I /// am /// Stuck
//
var allCqis = cities.Select(c => c.CityCqi); // gives you IObservable<IObservable<decimal>> ,
/// Need to use latest of each observable in allCqi and sum them up
//// How do I do it ?
}
}
约束条件
完整的源代码
可以通过单击Here下载源
最初提出的问题
我有一个热观测值,有多个热观测值...
IObservable<IObservable<decimal>>
我想要一个可观察的对象,当订阅时,它将使观察者知道内部所有可观察对象的所有“最新”十进制数字的总和。
我该如何实现?我尝试了CombineLatest(...),但无法正确执行。
谢谢
最佳答案
Rxx库具有CombineLatest()
重载的IObservable<IObservable<T>>
。如果使用此重载,则解决方案很简单:
var runningSum = allCqis
.Select(cqi => cqi.StartWith(0)) // start each inner sequence off with 0
.CombineLatest() // produces an IObservable<IList<decimal>>
.Select(cqis => cqis.Sum()); // LINQ operator Sum(IEnumerable<decimal>)
查看
Rxx.CombineLatest
的源代码对于查看如何“深入了解”问题可能很有用。关于c# - 如何获取N个热门Observable <decimal>实例的 “last”项的总和?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18800914/