覆盖QAbstractItemModel :: index并访问std :: map

时间:2011-05-08 09:29:25

标签: c++ qt

在我的程序中,我想使用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访问我的地图吗?

2 个答案:

答案 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;
}