在我的程序中,我想使用view = QListView的视图/模型模式以及我自己从QAbstractListModel继承的模型。我的数据类看起来像
class Avtomat
{
...
map<QString, State *> states;
...
};
在我的模型课程中
class AvtomatModel : public QAbstractListModel
{
...
Avtomat a;
...
};
我正在尝试重载QAbstractItemView :: index函数,以便我能够提供编辑数据映射的界面。 由于索引函数采用int行参数,因此通过提供以下
解决了该问题State* Avtomat::pStateFromIndex(int index) const
{
map<QString, State *>::const_iterator i;
int count = 0;
for (i = states.begin(); i != states.end() && count != index; ++i)
++count;
return (*i).second;
}
所以在我的索引函数中我喜欢这个
return createIndex(row, column, a.pStateFromIndex(row));
但这看起来很难看,因为我有O(n)。你能帮我设计一个更好的方法来使用int index访问我的地图吗?
答案 0 :(得分:2)
这是一个基本的数据建模问题。您需要检索数据的主要方式是什么?按键还是索引?
如果您只是通过索引(包括在模型中)访问它,那么您只是使用不适当的数据结构,并应切换到其他类似列表。
如果您确实需要按键查询,那么您有几个选项。如果效率不是一个巨大的驱动因素,那么你已经在做什么并没有错,特别是如果数据集很小的话。或者,您也可以维护基础数据的键映射和索引映射。这是一个简单而有效的解决方案,但它意味着您必须在两者之间管理一致性,并且如果数据集很大,则会产生内存开销,这可能很重要。或者您可以使用直接通过键和索引提供访问的数据结构。最终,这取决于您的具体情况和您正在使用的数据域。
文档中有一个很好的summary Qt容器类(以及std容器)。关于algorithmic complexity的部分可能对您特别感兴趣。
答案 1 :(得分:1)
另一种选择是使用向量来保存键值对中的数据。然后可以通过索引或键访问向量。 缺点是相对于std :: map,插入向量是昂贵的。
typedef std::pair<QString, State*> StateP;
typedef std::vector<StateP> States;
States states;
然后根据比较第一个元素的谓词按排序顺序维护向量。您可以通过O(1)中的索引或O(log n)中的键来查找项目。
struct StatePCompare {
bool operator()(StateP const& lhs, StateP const& rhs) const {
return (lhs.first < rhs.first);
}
};
void Avtomat::insert(QString key, State* state)
{
States::iterator i = std::lower_bound(states.begin(), states.end(), StatePCompare());
if ((i != states.end() && (i->first == key)) {
// key already exists, set the element
i->second = state;
}
else {
states.insert(i, state);
}
}
State* Avtomat::find(QString key)
{
States::iterator i = std::lower_bound(states.begin(), states.end(), StatePCompare());
if ((i != states.end() && (i->first == key)) {
return i->second;
}
return NULL;
}