Reputation: 53119
I have a QMap
that represents a database row. The items are indexed by column name:
QMap<QString, QVariant> mapOfItems_;
I then have a method to retrieve item by columnn name:
QVariant ImportDataSourceRow::byName( const QString& name )
{
if(mapOfItems_.contains(name))
return mapOfItems_.value(name);
else
throw NoSuchColumn();
}
I would like to also implement method to get item by column index (0
for first column):
QVariant ImportDataSourceRow::byIndex( size_t index )
{
// Now what?
}
How can I get the value at offset index
from the map? Is QMap
even guaranteed to be ordered as I need it to be?
Upvotes: 3
Views: 6197
Reputation: 11
Not recommended, but you can try to do it this way:
QList<QString> list = mapOfItems_.values();
if(index>=0 && index<list.count()) return list.at(index);
return QString();
Don't know how it works with a QVariant though.
Upvotes: 0
Reputation: 13005
Associative (dictionary-like) containers such as QMap
and std::map
rarely provide sequential indexing as internally they are typically implemented as tree-like data structures (for example, Red-Black Tree).
Notable exception is boost's flat_map
. It is implemented as a pair of contiguous arrays, where mapping of the key and value is expressed with array indices: mapped key and value have the same index. flat_map
provides method nth()
to access value by index:
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
"emulates" interface and behavior of the std::map
and sorts elements by key. You can use custom predicates.
Note that standard containers are suitable only for simplest database-like usecases. In general, databases is a very complicated topic. There are entire theories being built about it. If your dataset is large and you need to perform complicated indexing and queries, think about embedding one of the database engines available (e.g. SQLite, or other, more heavyweight ones).
Upvotes: 2
Reputation: 25155
The entries of a QMap are guaranteed to be ordered by key, in your case that'd be QString::operator<.
To get the position inside the map, you can use:
const auto it = mapOfItems.find(name);
const auto index = std::distance(mapOfItems.begin(), it);
Note that your byName() method would be more efficient if you used constFind() and throw if the returned iterator equals mapOfItems.constEnd(), instead of doing two lookups (contains and value()).
Upvotes: 2