我有几个指标需要“始终保持最新”。即当任何事情发生变化时,我需要重新计算“依赖”。我有几个级别,只有在计算前一级别时才应计算每个下一级别。让我用这幅闪亮的画面解释一下:
在某些时候假设法郎改变了。然后我们应该:
或者,如果Peso,Franc和Dinar一下子改变了,那么我们应该:
因此,只要Level 0
处的任何事情被打开,我们就应该重新计算所有其他级别。但
最直接的解决方案是:
我想我的问题很有名,可能你可以建议我一般众所周知的解决方案。我不想重新发明轮子:)谢谢!
答案 0 :(得分:2)
我认为基于等级的方法是不错的,假设听众总是处于较低的水平。
有一个包含实际数据的二维数组,第一个索引是级别,第二个是级别上的位置。让每个元素都有一个willBeRecalculated
标记。
每个级别都有一个toBeRecalculated
列表(所以列表数组)。
对于每个元素,都有一个包含2个整数的元素列表(侦听器) - 一个用于级别,一个用于索引。
对于要修改的每个元素,将元素添加到适当级别的toBeRecalculated
并将willBeRecalculated
设置为true。
然后从第一级到最后一级执行toBeRecalculated
,重新计算每个元素,将其willBeRecalculated
设置为false,并为每个侦听器查找适用的元素,如果willBeRecalculated
是的,什么都不做,否则,将willBeRecalculated
设置为true并将其添加到{(1}}的(听众)级别。
这种方法不会通过所有数据来检查需要修改/修改的内容,它只检查适用的元素,并且没有重复的计算。
为此:
(对于我的缩写,我只是取了每个单词的第一个字母。我正在使用0索引数组)
实际数据:
toBeRecalculated
<强>监听器:强>
[[E, U, P, F, D],
[E+U, F/D],
[E/E+D, F/D/P],
[P+E/E+U]
]
修改E:[(1,0), (2,0)] // E+U and E/E+U
U:[(1,0)] // E+U
P:[(2,1), (3,0)]
F:[(1,1)]
D:[(1,1)]
E+U:[(2,0)]
F/D:[(2,1)]
E/E+U:[(3,0)]
和E
:
将U
和E
添加到U
并将toBeRecalculated[0]
设置为true。
浏览willBeRecalculated
。
修改toBeRecalculated[0]
时,将E
设置为false并将willBeRecalculated
的{{1}}设置为true并将其添加到E+U
并设置{{ 1}}将willBeRecalculated
设为true并将其添加到toBeRecalculated[1]
。
修改E/E+U
时,请将willBeRecalculated
设置为false,然后检查toBeRecalculated[2]
的{{1}}并查看是真的,不要做任何事情。
然后浏览U
。在修改willBeRecalculated
时,请将E+U
设置为false并检查willBeRecalculated
的{{1}}并查看它是真的,不要做任何事情。
让侦听器成为指向元素而不是级别和索引变量的指针可能更好。
答案 1 :(得分:2)
好吧,当你说你正在处理关卡时,会想到某种树数据结构。
但是对于你的问题,我认为它可以模拟某种有向无环图。
您的图表可能看起来像这样(所有方向都向下)..
root
/ / | \ \
E U P F D
\ /
\ /
(Euro + Usd)
如果您像树形数据结构一样遍历此项,则每次更新货币时,您都会更新每个转化率一次。
答案 2 :(得分:0)
您所描述的内容可以通过reactive programming language.
轻松完成Qt的QML还提供了一种属性绑定机制,可以为UI完成此操作。
查看Qt属性绑定和其他反应式语言的实现可能会为您提供一些实现方法。
Wikipedia页面标识了Javascript,.NET,Python,Java,C ++和许多其他语言的反应式编程库。
答案 3 :(得分:0)
我认为你可以在这里使用多态。 有一个货币列表,每个货币都有一个带有指针(到基类)的矢量所有的depedant元素。
基类强制它们包含一个函数update()
,每次更新当前货币时都会调用该函数。
depedant元素反过来为他们所依赖的每种货币提供指针,并使用它们在update()
实现中更新自己。
#include<iostream>
#include <vector>
class c_node_combi_base;
class currency
{
std::vector<c_node_combi_base*> m_dependant;
double m_val;
public:
double value (void) const { return m_val; }
void reg (c_node_combi_base * p) { m_dependant.push_back(p); }
void update (double val);
};
class c_node_combi_base
{
std::vector<currency*> currencies;
public:
virtual void update (void) = 0;
};
template<size_t N, typename OP> // templated to differentiate types of nodes
class currency_node : public c_node_combi_base
{
};
struct divide_d
{
double operator() (const double x, const double y) const {return x/y;}
};
template<typename OPT> // node type 2
class currency_node<2u, OPT>
: public c_node_combi_base
{
currency *A, *B;
OPT _op;
double m_val;
public:
currency_node (currency * a, currency * b)
: A(a), B(b), _op(), m_val(_op(A->value(), B->value()))
{
A->reg(this);
B->reg(this);
}
void update (void)
{
m_val = _op(A->value(), B->value());
}
double value (void) { return m_val; }
};
void currency::update (double value)
{
m_val = value;
for (size_t i=0; i<m_dependant.size(); ++i)
{
m_dependant[i]->update();
}
}
这样可以:
int main (void)
{
currency franc, dinar;
franc.update(9.9);
dinar.update(3.3);
currency_node<2, divide_d> franc_dinar(&franc, &dinar);
std::cout << franc_dinar.value() << std::endl;
dinar.update(1.1); // updates franc_dinar automatically
std::cout << franc_dinar.value() << std::endl;
}
印刷:
3
9
也许您可以拥有std::vector<std::weak_ptr>
种货币,而每个节点对每种货币持有std::shared_ptr
因此货币可能不会超出范围/被销毁,除非没有更多节点参考它们