2012-05-15 38 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) 
     { 

     } 
    } 
}