2012-05-15 35 views
3

我需要找到最大,最小和平均有它自己的統計數據(ResultGroup類統計的基礎上,所有結果對象的列表中(統計)值的意思統計數據)。 當我添加對象時,值很容易更新,但如果我更改或刪除其中的一個,則需要再次查找統計信息。通常會有超過40,000個項目,我需要它是一個快速操作。最快和最簡單的方式來獲得最大值,最小值,從多個對象

有沒有比循環所有項目更好的方法?

public class ResultGroup 
{ 
    private Stats resultStats; 
    //I need an updated stats 
    public Stats ResultStats 
    { 
     get { return resultStats; } 
    } 
    private readonly ObservableCollection<Result> results = new ObservableCollection<Result>(); 

    public ObservableCollection<Result> Results 
    { 
     get 
     { 
      return results; 
     } 
    } 
    public ResultGroup() 
    { 
     this.resultStats = new Stats(); 
     this.results.CollectionChanged += new NotifyCollectionChangedEventHandler(CollectionChanged); 
    } 

    private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      //It works ok on add. 
      Stats lastResultStat = this.results[this.results.Count - 1].Stat; 
      if (resultStats.Max < lastResultStat.Max) 
       resultStats.Max = lastResultStat.Max; 

      if (resultStats.Min > lastResultStat.Min) 
       resultStats.Min = lastResultStat.Min; 

      resultStats.Mean = (resultStats.Mean * (this.results.Count - 1) + lastResultStat.Mean)/this.results.Count; 
     } 
     else if (e.Action == NotifyCollectionChangedAction.Reset) 
     { 
      this.resultStats = StatsFactory(); 
     } 
     else if (e.Action == NotifyCollectionChangedAction.Remove) 
     { 
      //Need to find the stats here 
     } 
     else if (e.Action == NotifyCollectionChangedAction.Replace) 
     { 
      //Need to find the stats here 
     } 
    } 

    private Stats StatsFactory() 
    { 
     Stats dataStats = new Stats(); 
     dataStats.Max = float.MinValue; 
     dataStats.Min = float.MaxValue; 
     dataStats.Mean = 0; 
     return dataStats; 
    } 
} 

public class Result 
{ 
    private float[] data; 

    //Another class will fill data and set the Stats (max, min, mean) 
    public float[] Data 
    { 
     get { return data; } 
    } 

    public Result(int lenght) 
    { 
     this.data = new float[lenght]; 
    } 

    private Stats stat; 
    public Stats Stat 
    { 
     get { return stat; } 
     set { stat = value; } 
    } 
} 

public class Stats 
{ 
    public float Max { get; set; } 
    public float Min { get; set; } 
    public float Mean { get; set; } 
} 
+1

在[文檔'NotifyCollectionChangedEventArgs展望'](http://msdn.microsoft.com/en-us/library/system.collections.specialized.notifycollectionchangedeventargs.aspx),你想查看'NewItems'和'OldItems'屬性並重新計算什麼是添加或刪除。 – mellamokb

+0

Yeaah不錯!我看看它。謝謝 – Pedro77

+0

重新計算意思我認爲我可以使用舊的項目,但最大和最小值不可能。 – Pedro77

回答

1

您是否嘗試過在CollectionChanged中使用像Min,Max和Average這樣的LINQ運算符?

+0

林諾使用LINQ,但我看看它,謝謝 – Pedro77

1

我認爲你可以緩存最大值,最小值當你第一次初始化集合,然後你可以比較緩存的值新值。

我可以建議在未來的算法:如果我有一個巨大的值列表我會分裂它的範圍,並集合每個範圍。對於每個集合,我都有一個緩存的平均值,當集合發生變化時將重新計算。當我添加新值(或更改)時,我會看到元素的統計信息並找到具有所需範圍的集合。在這種情況下,我們得到一個統計數據作爲附加索引,我們必須在特定集合(第一個,最後一個)中找到最大值和最小值。我們可以從所有集合的平均值中獲得平均值。最大值,最小值我們可以在第一個和最後一個集合中緩存。

+0

這是OP已經在做什麼,只需要幫助如何做到這一點... – mellamokb

1

您是否嘗試過使用數據庫?

因爲數據庫有索引可以幫助。還可以看看KDB或SAP的HANA,它具有基於垂直/列的數據庫,可以毫秒級地滲透數百萬行。

也許像SqlLite這樣基於簡單文件的數據庫會有所幫助。

3

刪除的項目時(應與減少內存使用情況,以及如果你正在處理大量數據的幫助),你需要通過全項,當刪除的項目等於當前最小/最大隻有循環。

更換項目時,您可以通過所有項目,只需要循環時,已刪除的項目等於當前最小/最大和新產品更大/小。

+0

你是對的!但是什麼意思呢?那麼,我會考慮一下吧... – Pedro77

0

//更好地與集合內的所需屬性的自定義集合,然後對收集來存儲聚合值之上的LINQ ...

public class ObserCol: ObservableCollection<int> 
{ 

    private int _maxValue = 0; 

    public ObserCol() { 
     base.CollectionChanged +=new NotifyCollectionChangedEventHandler(CollectionChanged); 
    } 

    public int MaxValue{ 
     get { 
      return _maxValue; 
     } 
    } 

    private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      //Can use Linq to get the Max or Other Aggregate values.. 
     } 
     else if (e.Action == NotifyCollectionChangedAction.Reset) 
     { 

     } 
     else if (e.Action == NotifyCollectionChangedAction.Remove) 
     { 

     } 
     else if (e.Action == NotifyCollectionChangedAction.Replace) 
     { 

     } 
    } 
}