我需要找到具有自己的统计数据的对象列表的max,min和mean(stats)值(ResultGroup类统计数据,基于所有Result统计数据)。 当我添加对象时,值很容易更新,但如果我更改或删除其中一个,那么我需要再次查找统计信息。通常会有超过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; }
}
答案 0 :(得分:3)
删除项目时,只需删除所有项目,当删除的项目等于当前的最小/最大值时。
更换项目时,只需删除所有项目,当删除的项目等于当前的最小/最大值且新项目更大/更小时。
答案 1 :(得分:1)
您是否尝试在CollectionChanged中使用MinQ,Max和Average等LINQ运算符?
答案 2 :(得分:1)
我认为您可以在首次初始化集合时缓存max,min值,然后可以将新值与缓存值进行比较。
我可以建议下一个算法:如果我有一个巨大的值列表,我会将它分成范围并为每个范围制作一个集合。对于每个集合,我将有一个缓存的平均值,当集合被更改时将重新计算。当我添加新值(或更改)时,我会看到元素的统计信息并找到所需范围的集合。在这种情况下,我们将统计数据作为附加索引,我们必须仅在某些集合中找到最大值和最小值(第一个,最后一个)。我们可以从所有集合的平均值获得的平均值。我们可以在第一个和最后一个集合中缓存的Max,Min值。
答案 3 :(得分:1)
您是否尝试过使用DB?
因为DB有索引可以提供帮助。另请参阅KDB或SAP的HANA,它具有基于垂直/列的数据库,可以在几毫秒内渗透数百万行。
也许像SqlLite这样基于简单文件的数据库会有所帮助。 (如果您处理大量数据,这应该有助于减少内存使用量)
答案 4 :(得分: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)
{
}
}
}