How to correctly access QMap in QAbstractTableModel::data() - qt

I got a QMap with an identifier and a corresponding object. When subclassing QAbstractTableModel::data() you get a QModelIndex with row and column, respectively. Each row should represent one object (QAbstractTableModel::rowCount() is myMap->size()).
Is it legit to get the current object via
myMap->values().at(index.row())
Has this implications (sorting, inserting), because the identifiers of the (unsorted) map are by-passed? I mean for QAbstractTableModel::setData() I need to do the same map identifier by-passing?! Thanks.

Quite late answer, but can still be useful:
(myMap->constBegin() + index.row()).key();
(myMap->constBegin() + index.row()).value();
will do the trick avoiding the copy of values() method

When you say "identifier", I assume you mean key, and "the corresponding object" is the value. QMap is by-definition sorted by key.
If you never intend to use the QMap key-value functionality, you should consider storing your values in a QList container and accessing that based on the row index as you suggested.

QMap::values returns all values in ascending order of their keys, so probably your code will work. Still, I'd use something like following:
myMap[this->index(index.row(), 0).data().toString()]
provided that you call it from QAbstractTableModel, and your keys are in 0th column.

Related

DynamodbDB query without a range key

I have table defined with two column, column 1 is the hash key and column 2 is the range key.
I want to get all items defined with the same hash key (so the range key doesn't matter).
I tried to use the new KeyPair().withHashKey(k). But it will throw exception saying that no RANGE key value present.
Is the only option I have is to do a scan for the table to achieve this?
I think the problem is that you are trying to use the GetItem call, which requires the complete key, and only returns one item. You need to use the Query call, and pass in a KeyExpression that only includes the partition key.

Is it possible to provide custom logic for Secondary Index key creation?

For my secondary index, I would like to have a key column which is a semicolon separated data of 2 columns in the base table.
Is it possible to create a custom logic to generate such value for the key column in secondary index?
Unfortunately you can only use another key, verbatim- no transformations or custom logic.
If this is essential for you, however, you can enable DynamoDB streams on your table, and use them to trigger a lambda. The lambda could either:
Adds/update a column with your custom logic value in your table that you'd use for your GSI (just be careful to check the UPDATE document so you don't get stuck in an infinite loop!)
Populate/update a second table with the custom logic key and any attributes you want.
I would probably lean towards the former, because then removal and synchronization of data is still DynamoDB's responsibility.
n.b. if you only need your key to be the two combined values, you could just use one as a partition and the other as a sort for your GSI.

Delete a key-value pair in BerkeleyDB

Is there any way to delete key-value pair where the key start with sub-string1 and ends with sub-string2 in BerkeleyDB without iterating through all the keys in the DB?
For ex:
$sub1 = "B015";
$sub2 = "5646";
I want to delete
$key = "B015HGUJJ75646"
Note: It is guaranteed that there will be only one key for the combination of $sub1 and $sub2.
This can be done by taking an iterator of the DB and checking every key for the condition, but that will be very in-efficient for large DBs. Is there any way to do it without iterating through the complete DB?
If you're using a RECNO database, you're probably out of luck. But, if you can use a BTREE, you have a couple of options.
First, and probably easiest is to iterate over only the portion of the database that makes sense. Assuming you're using the default key comparison function, you can use DB_SET_RANGE to position the starting cursor (iterator) at the start of your partial key string. In your example, this might be "B0150000000000". You then scan forwards with DB_NEXT, looking at each key in turn. When either you find the key you're looking for, or if the key you find doesn't start with "B015", you're done.
Another technique that could be applicable to your situation is to redefine the key comparison function. If, as you state, there is only one combination of $sub1 and $sub2, then perhaps you only need to compare those sections of the keys to guarantee uniqueness? Here's an example of a full string comparison (I'm assuming you're using perl, just from the syntax you supplied above) from https://www2.informatik.hu-berlin.de/Themen/manuals/perl/DB_File.html :
sub Compare
{
my ($key1, $key2) = #_ ;
"\L$key1" cmp "\L$key2" ;
}
$DB_BTREE->{compare} = 'Compare' ;
So, if you can rig things such that you're only comparing the starting and ending four characters, you should be able to drop the database iterator directly onto the key you're interested in.

How to create three dimensional array with QHash?

I want to create QHash with three arguments:
QHash <int, QString, float> myhash;
I know that I have to use nested QHash, so I did:
QHash <int, QHash<QString, float> > myhash;
But I could not figure out how I can insert values to myhash.
I tried to create another Qhash and insert this into my myhash, but I does not make any sence, since I have exactly 1 pair data for one key.
What I want basically is :
0, "string1", 1.5
1, "string2", 1.2 etc.
How I can create efficiently (in terms of lookup time (the reason I am using QHash)) the above arrays. And how to insert values afterwards.
Thanks forward.
With QHash <int, QHash<QString, float> > myhash;, you can simply do this to set values:
myhash[42]["fortytwo"] = 42.42;
You can use the same syntax to access elements, but note that when accessed with non-const operator[], these entries will actually be created in the hash. So it's often better to use value() method:
if (myhash.value(43).value("fortytwo") >= 42) { /*...*/ }
Note that for QHash and QMap, accessing key which is not in the map is ok, default constructed value is returned in that case. Above for first it means and empty hash, and for second, value 0.0f.
To compare this to the method of using QPair from the other answer, this has the particular advantage that you can access elements by "rows" easily, if it matters for your use case (just make sure you have the nested hashes in the right order). Also, with this method, you could use different container for different dimensions, like if you need one dimension to be sorted use QMap (which is sorted by key) for that, and QHash (which is more efficient) for the dimension which doesn't need sorting. Additionally, you can have any number of dimensions easily, just add more nested containers.
On the other hand, if the key is logically a pair of values which are never separated, and data is not really (from programming perspective) organized as a two-dimensional table, then using QPair for key is probably better.
Unrelated to the question: to improve efficiency, in Qt 5 and C++11 you could use QStringLiteral("fortytwo") to have the QString created already at compile time.
Use a QPair as your key:
QHash<QPair<int,QString>,float> myhash;
Insert values:
myhash.insert(QPair<int,QString>(1,"string1"),12.);
or
QPair<int,QString> p(1,"string1");
myhash[p] = 12.

How to get an attribute named ID in gremlin

I'm getting weird results while writing a gremlin query. I can happily use the has function for most of the attributes for my nodes, for example "().has('name', 'VerisignCzagExtension').property('id')" will return v5086. But when I attempt to use the has function with the attribute id it never returns true. for example "().has('id', 'v5086').property('id')" returns no results. Anyone have any idea why this is happening?
Thanks.
Internally, Neo4j stores all IDs as java.lang.Long objects. This is a special behavior for id property only. All other properties are stored with their implied data types. That's a reason why has('name', 'VerisignCzagExtension') works (because name property is excluded from this special behavior meant for id). I'm assuming v5086 is being type casted to java.lang.Long, thus losing it's real value. That could explain zero results after a has('id', 'v5086') Gremlin step.
AFAIK, id property is immutable (can't be changed). If you need to make id look ups for vertices using a has Gremlin step, it would look something like has('id', 5086L) assuming that the vertex id is 5086 and is being stored as a java.lang.Long value. An extra L is for explicit java.lang.Long type-casting, Neo4j would assume java.lang.Integer if you don't add that L and your Gremlin step would result in zero results again.
Finally, you might want to call your named ID something else, like a property with key name.
Hope this helps.

Resources