簡體   English   中英

如何得到N hot Observable的“最后”項目的總和 <decimal> 實例?

[英]How to get Sum of “last” items of N hot Observable<decimal> instances?

編輯:2013年9月15日 - 我正在描述我的情景進一步分解為幫助每個人更好地了解我的情況的步驟。 添加了整個應用程序的源代碼以供下載。 如果要跳轉到原始問題,請向下滾動到最后一個標題。 請讓我知道這些問題。 謝謝

摘要

阿拉斯加州首府朱諾有一個AST(阿拉斯加州警官)總部大樓,他們希望在這個大屏幕上顯示一個顯示和自動更新的單個號碼。 該號碼稱為(犯罪商數指數)或CQI

CQI基本上是一個計算出的數字,用於顯示當前的國家犯罪情況......

如何計算?

運行屏幕的程序是.NET WPF應用程序,它通過Hot IObservable流不斷接收CrimeReport對象。

每個城市計算CQI,然后采用所有城市的Sum(),稱為國家CQI以下是計算國家CQI的步驟

第1步 - 接收犯罪數據

每次報告犯罪時,CrimeReport都會發送到.NET應用程序。 它具有以下組件

犯罪日期時間

- 市/轄縣

SeverityLevel - 嚴肅/非嚴重

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的計算通過以下公式完成

如果嚴重犯罪總數與非嚴重犯罪總數之比小於1

然后

城市的CQI =比率x估計求解時間的最小值

其他

城市的CQI =比率x最大估計求解時間

這是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);
 }
}

現在我們有城市DTO對象維護城市的CQI值並通過IObservable暴露實時CQI,阿拉斯加州的Capital希望Sum()將所有城市的CQI顯示為阿拉斯加的CQI並在屏幕上顯示它們在參與CQI計划的城市/縣的任何地方報告的犯罪應立即對國家的CQI產生影響

第3步 - 為州填寫城市數據

現在我們必須計算整個州的CQI,這是大屏幕上的實時更新,我們有State的視圖模型,名為MainViewModel

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 ?
     }
}

約束

  • 並非所有阿拉斯加城市都參與州的CQI計划,但城市正在日復一日地注冊,因此我無法列出並添加所有城市,無論注冊是否也不實用。 所以它是IObservable,它只維護那些不僅參與但也發送了至少一個CrimeReport對象的城市。

完整源代碼

點擊此處即可下載來源

原來問的問題

我有一個熱的可觀察的多個熱觀察點......

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的源代碼可能有助於了解問題如何在“引擎蓋下”解決

很多問題! 也許是時候了解你的Rx技巧? 幾乎所有最近的問題都在我的網站IntroToRx.com中介紹 深入了解Rx,可以比在論壇上提問更快地回答這些相當簡單的問題。 你應該可以在不到3天的時間內閱讀這本書。

無論如何....

1你想要一筆運行金額或者最后一筆金額嗎?

2那么,您是否想要所有流的所有值或每個流的總和的總和?

要獲取序列的單個和值,請使用.Sum()運算符。 http://introtorx.com/Content/v1.0.10621.0/07_Aggregation.html#MaxAndMin

要獲得運行總計,請使用“ Scan運算符。 http://introtorx.com/Content/v1.0.10621.0/07_Aggregation.html#Scan

所以答案可能是這樣的(未經測試):

sources.Select(source=>source.Scan(0m, (acc, value)=>acc+=value)).Merge();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM