2016-05-12 134 views
0

我有一个代表数据库行的QMap。该项目是按列名索引:在QMap的特定偏移处获取项目

QMap<QString, QVariant> mapOfItems_; 

然后我有通过columnn名称检索项目的方法:

QVariant ImportDataSourceRow::byName(const QString& name) 
{ 
    if(mapOfItems_.contains(name)) 
     return mapOfItems_.value(name); 
    else 
     throw NoSuchColumn(); 
} 

我想也实现方法,通过列索引获取项目(0为第一列):

如何从地图中获得偏移量为index的值? QMap甚至保证按我的需要订购?

+0

'return * std :: next(mapOfItems_.begin(),index);'? (请注意,它是线性的)。 – Jarod42

+0

地图不适合按索引搜索。这就是为什么没有相应的API。 – vahancho

回答

1

联想(类似于字典的)容器,如QMapstd::map很少提供顺序的索引来确定内部它们通常作为树状数据结构来实现(例如,Red-Black Tree)。

值得注意的例外是boost的flat_map。它被实现为一对连续的数组,其中键和值的映射用数组索引表示:映射键和值具有相同的索引。 flat_map由索引提供方法nth()访问值:

boost::container::flat_map<std::string, float> geek_numbers; 
geek_numbers.emplace("pi", 3.14f); 
geek_numbers.emplace("e", 2.72f); 
geek_numbers.emplace(
    "Answer to the Ultimate Question of Life, The Universe, and " 
    "Everything", 
    42.0f); 
auto 0th = geek_numbers.nth(0); // 42.0f 
auto 1st = geek_numbers.nth(1); // 2.72f 
auto 2nd = geek_numbers.nth(2); // 3.14f 

flat_map“模拟”的std::map的接口和行为,并通过排序关键要素。您可以使用自定义谓词。

请注意,标准容器仅适用于最简单的类数据库使用案例。一般来说,数据库是一个非常复杂的话题。有关于它的完整的theories。如果您的数据集很大并且需要执行复杂的索引和查询,请考虑嵌入可用的数据库引擎之一(例如SQLite或其他更多heavyweight ones)。

+0

在另一个答案中,@tomáš-zato说列名不是名字。所以这个信息在使用flat_map时会丢失,对吧? – Daniel82

1

QMap的条目保证按键排序,在你的情况下是QString :: operator <。

为了让地图中的位置,你可以使用:

const auto it = mapOfItems.find(name); 
const auto index = std::distance(mapOfItems.begin(), it); 

注意,你的绰号(),如果你使用constFind(方法会更有效),并抛出如果返回的迭代器等于mapOfItems.constEnd (),而不是做两个查找(包含和值())。

+0

我想我不能使用'QMap',因为列顺序不是名字。谢谢你的回答。你能推荐我应该使用什么吗?也许两个数组 - 名称和值? –

+0

如果你的项目列表不是太大,一个简单快捷的方法就是QVector >对象,并且你可以使用at()和name来访问你需要迭代的索引,但如果名单很小,那是可以接受的。 – Daniel82

+0

或者只是使用一个向量,其条目按列索引排序。但是,然后byName()将具有O(n)复杂性而不是O(log n)。 –

0

不推荐,但你可以尝试这样来做:

QList<QString> list = mapOfItems_.values(); 
if(index>=0 && index<list.count()) return list.at(index); 
return QString(); 

不知道它是怎么用的QVariant工作虽然。