问题是:我有一个包含时间和值(时间=长毫秒和双值)的数据列表。我现在需要计算不同时间范围内的几个平均值
我每秒最多可以得到50个值,但有时只有几个值,需要保持最后10秒,所以500个值。
我想要的是:计算时间的平均值
我可以保证没有时间是双倍的,所以它可以用作一把钥匙。
目前,我使用一个数组来存储值,并且有一个位置标记,一旦达到500,它就会重置为0,所以旧的条目会被重新调整样式。我可以很容易地改变。
我不确定最快的方法是什么,例如手动搜索数组或使用列表、hashMap、集合(使用comparator?)否则。我找不到一个类似(java)列表的函数,其中我有一个内置搜索键
性能比简单的编码更重要。
被指向正确的方向会很好。
每次有新值进来时,我都会计算最后10个值的平均值,即每秒30-50次计算,这是最重要的数据。我需要区分测量中的小错误和实际变化。我额外计算每1/10秒的平均值(这可能会被删除),最后是一秒的平均值和最后10秒的平均值。这是每秒12次的额外平均计算。减少计算次数并不是一个真正的选择。
由于这有点抽象,下面是一个数据的示例(其中avg是最后10个值的计算结果,但这不是程序逻辑)。
value Avg timeReading timeReadingISO
1024,6668701172 - 1385408750828 2013-11-25 19:45:50
1024,6668701172 - 1385408751350 2013-11-25 19:45:51
1024,6668701172 - 1385408751859 2013-11-25 19:45:51
1024,6683349609 - 1385408752373 2013-11-25 19:45:52
1024,6683349609 - 1385408752878 2013-11-25 19:45:52
1024,6689453125 - 1385408753385 2013-11-25 19:45:53
1024,6689453125 - 1385408753895 2013-11-25 19:45:53
1024,6721191406 - 1385408754406 2013-11-25 19:45:54
1024,6721191406 - 1385408754912 2013-11-25 19:45:54
1024,6774902344 - 1385408755432 2013-11-25 19:45:55
1024,6774902344 1024,67 1385408755994 2013-11-25 19:45:55
1024,6774902344 1024,67 1385408756502 2013-11-25 19:45:56
1024,6837158203 1024,67 1385408757012 2013-11-25 19:45:57
1024,6837158203 1024,67 1385408757520 2013-11-25 19:45:57
1024,689453125 1024,68 1385408758028 2013-11-25 19:45:58
1024,689453125 1024,68 1385408758536 2013-11-25 19:45:58
1024,6938476563 1024,68 1385408759055 2013-11-25 19:45:59
1024,6938476563 1024,68 1385408759560 2013-11-25 19:45:59
1024,6990966797 1024,68 1385408760075 2013-11-25 19:46:00
1024,6990966797 1024,69 1385408760579 2013-11-25 19:46:00
1024,7038574219 1024,69 1385408761086 2013-11-25 19:46:01
1024,7038574219 1024,69 1385408761596 2013-11-25 19:46:01
1024,7111816406 1024,69 1385408762103 2013-11-25 19:46:02
1024,7111816406 1024,70 1385408762606 2013-11-25 19:46:02
1024,7111816406 1024,70 1385408763112 2013-11-25 19:46:03
1024,7111816406 1024,70 1385408763622 2013-11-25 19:46:03
1024,7172851563 1024,70 1385408764128 2013-11-25 19:46:04
1024,7172851563 1024,71 1385408764637 2013-11-25 19:46:04
1024,7208251953 1024,71 1385408765149 2013-11-25 19:46:05
1026,5457763672 - 1385474621756 2013-11-26 14:03:41
1026,6057128906 - 1385474621790 2013-11-26 14:03:41
1026,6257324219 - 1385474621823 2013-11-26 14:03:41
1026,6057128906 - 1385474621858 2013-11-26 14:03:41
1026,6257324219 - 1385474621890 2013-11-26 14:03:41
1026,6257324219 - 1385474621921 2013-11-26 14:03:41
1026,6057128906 - 1385474621956 2013-11-26 14:03:41
1026,5457763672 - 1385474621988 2013-11-26 14:03:41
1026,6557617188 - 1385474622022 2013-11-26 14:03:42
1026,6657714844 - 1385474622057 2013-11-26 14:03:42
1026,6257324219 1026,61 1385474622090 2013-11-26 14:03:42
1026,6057128906 1026,62 1385474622123 2013-11-26 14:03:42
1026,6657714844 1026,62 1385474622159 2013-11-26 14:03:42
1026,6557617188 1026,62 1385474622193 2013-11-26 14:03:42
1026,6557617188 1026,63 1385474622227 2013-11-26 14:03:42
1026,6257324219 1026,63 1385474622260 2013-11-26 14:03:42
1026,6257324219 1026,63 1385474622298 2013-11-26 14:03:42
1026,6557617188 1026,63 1385474622330 2013-11-26 14:03:42
1026,6257324219 1026,64 1385474622365 2013-11-26 14:03:42
1026,6257324219 1026,64 1385474622401 2013-11-26 14:03:42
1026,6257324219 1026,64 1385474622431 2013-11-26 14:03:42
1026,5758056641 1026,64 1385474622466 2013-11-26 14:03:42
1026,6057128906 1026,63 1385474622501 2013-11-26 14:03:42
1026,5457763672 1026,63 1385474622533 2013-11-26 14:03:42
1026,5457763672 1026,62 1385474622565 2013-11-26 14:03:42
1026,6057128906 1026,61 1385474622599 2013-11-26 14:03:42
1026,6057128906 1026,60 1385474622631 2013-11-26 14:03:42
1026,5758056641 1026,60 1385474622665 2013-11-26 14:03:42
1026,5457763672 1026,59 1385474622702 2013-11-26 14:03:42
1026,6057128906 1026,59 1385474622734 2013-11-26 14:03:42
1026,6557617188 1026,58 1385474622766 2013-11-26 14:03:42
1026,5758056641 1026,59 1385474622800 2013-11-26 14:03:42
1026,6057128906 1026,59 1385474622836 2013-11-26 14:03:42
1026,6057128906 1026,59 1385474622868 2013-11-26 14:03:42
1026,5158691406 1026,59 1385474622901 2013-11-26 14:03:42
1026,5457763672 1026,59 1385474622935 2013-11-26 14:03:42
1026,6856689453 1026,58 1385474622966 2013-11-26 14:03:42
在Maciej的答案中缓存平均值组是一种有效的方法。当前列表的一个简单方法是Java的SortedSet,它是一个接口,因此最终将使用TreeSet。
创建一个比较对象来存储时间和值,或者为SortedSet创建一个比较器。确保您是根据时间(而不是值)排序的。
public class Holder implements Comparable
{
private double time, value;
public Holder (double t, double v)
{
this.time = t;
this.value = v;
}
public double getValue()
{ return this.value; }
public double getTime()
{ return this.time; }
//You may want a better comparator.
public int compareTo( Holder h )
{
return this.getTime < h.getTime() ? -1 : 1;
}
}
只需为集合添加正常值,它们将根据时间自动排序。当你想要过去10秒的平均值时,找到当前时间并调用sortedSet。tailSet(新的CustomObject(currentTime-10000))
。现在迭代返回的集合以计算平均值。
SortedSet<Holder> slice = allHolders.tailset( new Holder( currentTime - 10000 ) );
double sum = 0.0;
for( Holder h : slice )
{
sum += h.getValue();
}
double result = sum / slice.size();
您可以使用查找时间组。subSet()
如果您觉得平均呼叫有延迟。
首先,在计算平均值时,您应该创建一个结构的副本(或者使用一个线程安全的副本,并且在添加或删除过程中遍历它不会造成疼痛),除非您在一个线程中执行所有操作。
我猜你的集合中的元素是按区域排序的,因为你会按顺序接收更新(如果不是的话,请查找排序列表的等效项)。
我的方法是选择平均测量值的最小间隔。比如说10个值。然后,您可以创建50个集合(大小为10),其中每一个集合都属于同一级别,这为您提供了计算平均值的方法。然后,您可以选择要计算的平均值。只需计算集合的平均值 更重要的是,一旦计算出给定集合的平均值,就不会改变,所以可以缓存它
请注意,您不必将值从一个集合转移到另一个集合,因为已经处理了最小间隔。如果缓冲区中出现了新的10个元素,您只需重新分配引用即可。
/* initializing */
MySlicedCollection buffer = new MySlicedCollection();
MySlicedCollection[] mscArray = new MySlicedCollection[50];
/* when every 10 values came in */
for(int i = mscArray.length-1; i > 0 ; --i) {
mscArray[i] = mscArray[i-1];
}
mscArray[0] = buffer;
buffer = new MySlicedCollection();
/* avg of all collection */
for(MySlicedCollection msc : mscArray) {
sum += msc.getAverage();
}
sum /= 50;
你还应该考虑使用之前的结果计算平均值。如果你必须计算1秒和2秒的平均值,那么你可以把剩余的平均值加到已经计算的平均值上一秒钟,然后除以2。
/* avg for one second */
for(int i = 0; i < 5; ++i) {
sumOneSec += mscArray[i].getAverage();
}
sumOneSec /= 5;
/* avg for two seconds */
for(int i = 5; i < 10; ++i) {
sumTwoSec += mscArray[i].getAverage();
}
sumTwoSec = ((sumTwoSec/5) + sumOneSec) / 2;
但请记住有人说过的话:“先衡量然后行动”——也许你的表现就足够了?
avg = (avg * 50 - oldestValue + newValue)/50;
不幸的是,由于浮点变量的有限表示,这会给计算带来一点错误,但由于使用的是双值,我认为不需要这样的精度。类似的解决方案可以提供给另一个平均值,但这需要更多的思考:)
问题内容: 我有一个大约有450万行的Postgres表。列基本上只是 当查询该表,你有一个长整型,并希望找到对应的范围内的数据,并包括该值。索引此表以进行快速查找的最佳方法是什么? 问题答案: 一个 多列索引 具有反向排序顺序: 这样,可以将索引向前扫描到足够高的位置,然后对所有行进行扫描直到太低为止- 一次扫描。这就是为什么要对索引执行排序顺序的主要原因:将不同的排序顺序组合在具有不同顺序的多
问题内容: 我知道范围有3种类型:范围,步幅和间隔。 快速间隔是多少?以及它们使用的一个例子是什么? http://zh.wikipedia.org/wiki/间隔(数学) 编辑:这就是beta 5 xcode 6发行说明所说的: •可比较值的间隔,可以有效地检查是否包含。间隔用于switch语句中的模式匹配,并由〜=运算符使用。 问题答案: 从Swift 3(使用Xcode 8)开始,类型不再存
问题内容: 嗨,我正在尝试检查当前时间是否在某个时间范围内,例如8:00-16:30。下面的代码显示可以将当前时间作为字符串获取,但是不确定如何使用此值来检查它是否在上面指定的时间范围内。任何帮助将不胜感激! 问题答案: 有很多方法可以做到这一点。就我个人而言,如果可以避免的话,我不喜欢使用字符串。我宁愿处理日期组件。 下面的代码创建的日期为8:00和16:30,然后比较日期以查看当前日期/时间是
问题内容: 我有一个元组列表,每个元组都是一个。我正在尝试合并所有重叠的时间范围,并返回不同时间范围的列表。例如 这是我的实现方法。 我想弄清楚是否 是某些python模块中的内置函数可以更有效地做到这一点吗?要么 有没有达到相同目标的更Python方式? 感谢您的帮助。谢谢! 问题答案: 使用Pythonic可以提高效率的几种方法: 消除了构造,因为该算法应在主循环中删除重复项。 如果只需要遍历
问题内容: 例如,我有一个数字数组 我想找到特定范围内元素的所有索引。例如,如果范围是(6,10),则答案应该是(3,4,5)。有内置的功能可以做到这一点吗? 问题答案: 您可以用来获取索引并设置两个条件:
问题内容: 给定一个数字列表,人们如何发现第()个元素与其第()个元素之间的差异? 使用表达式还是列表理解更好? 例如: 给定一个列表,我们的目标是要找到一个列表,因为,等等。 问题答案: