2011-05-08 41 views
1

在我的程序中,我想使用視圖/模型模式與view = QListView和我從QAbstractListModel subclassed我自己的模型。我的數據類看起來像覆蓋QAbstractItemModel :: index和訪問std :: map

class Avtomat 
{ 
... 
map<QString, State *> states; 
... 
}; 

在我的模型類

class AvtomatModel : public QAbstractListModel 
{ 
    ... 
    Avtomat a; 
    ... 
}; 

我試圖重載QAbstractItemView中::索引功能,使我能夠提供的數據編輯地圖界面。 作爲指數函數接受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索引訪問我的地圖嗎?

回答

2

這是一個基本的數據建模問題。您需要檢索數據的主要方式是什麼?按鍵或索引?

如果你只有通過索引訪問它(包括在模型中),那麼你只是使用不適當的數據結構,應該切換到其他類似的列表。

如果你確實需要按鍵查詢,那麼你有幾個選項。如果效率不是一個巨大的驅動因素,那麼你已經在做什麼沒有問題,特別是當數據集很小時。或者,您也可以同時維護密鑰和索引映射到您的基礎數據。這是一個簡單而有效的解決方案,但它意味着您必須在兩者之間保持一致的管理,並且存在一個內存開銷,如果您的數據集很大,這可能很重要。或者你可以使用一個數據結構直接提供鍵和索引的訪問。最終取決於您的具體情況和您正在使用的數據域。

在文檔中有Qt容器類的良好summary(以及std容器)。關於algorithmic complexity的部分可能對您特別有意思。

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