How to create three dimensional array with QHash? - qt

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.

Related

How to insert an element into the middle of an array (json) in SQLite?

I found a method json_insert in the json section of the SQLite document. But it seems to be not working in the way that I expected.
e.g. select json_insert('[3,2,1]', '$[3]', 4) as result;
The result column returns '[3,2,1,4]', which is correct.
But for select json_insert('[3,2,1]', '$[1]', 4) as result;
I am expecting something like '[3,2,4,1]' to be returned, instead of '[3,2,1]'.
Am I missing something ? I don't see there is an alternative method to json_insert.
P.S. I am playing it on https://sqlime.org/#demo.db, the SQLite version is 3.37.2.
The documentation states that json_insert() will not overwrite values ("Overwrite if already exists? - No"). That means you can't insert elements in the middle of the array.
My interpretation: The function is primarily meant to insert keys into an object, where this kind of behavior makes more sense - not changing the length of an array is a sacrifice for consistency.
You could shoehorn it into SQLite by turning the JSON array into a table, appending your element, sorting the result, and turning it all back into a JSON array:
select json_group_array(x.value) from (
select key, value from json_each('[3,2,1]')
union
select 1.5, 4 -- 1.5 = after 1, before 2
order by 1
) x
This will produce '[3,2,4,1]'.
But you can probably see that this won't scale, and even if there was a built-in function that did this for you, it wouldn't scale, either. String manipulation is slow. It might work well enough for one-offs, or when done infrequently.
In the long run, I would recommend properly normalizing your database structure instead of storing "non-blob" data in JSON blobs. Manipulating normalized data is much easier than manipulating JSON, not to mention faster by probably orders of magnitude.

Using adafruit_debouncer on a keyboard matrix

I am implementing a key matrix in Circuitpython on a Raspberry Pi Pico.
I have gotten to the point where I can scan and read fine. Now I need to add debouncing. I would like to use adafruit_debouncer for that.
First I fell for the mistake of simply debouncing the column input-pins with hilarious results as the debouncer tried to make sense of the values while the rows where being scanned...
Now I want to create a debouncer for each key and I think I should be able to use adafruit_debouncer by not giving it a DigitalIO-instance to work on but a lambda that looks at a specific cell in my two-dimensional array of key states.
Given two suitably sized 2D-arrays of keystates and debouncers I create them like this:
for rowindex in range(len(rowpins)):
for colindex in range(len(colpins)):
debouncers[rowindex][colindex] = adafruit_debouncer.Debouncer(lambda: keystates[rowindex][colindex])
After doing each scan that updates keystates[][], putting in Trues and Falses according to wether a key is down or not, I then iterate over debouncers[][], call update() on each and then query their value.
Unfortunately no debouncer seems to be able to see the True values from the array. At least none ever report a True themselves.
What is my mistake?

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 correctly access QMap in QAbstractTableModel::data()

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.

Alternative to search through a packed+unpacked array in systemverilog

I have this strange situation where i am currently doing this:
if (!this.randomize(delay) with {delay inside {strm};})
......
where
rand bit [2:0] delay;
bit [15:0] strm [bit [15:0]];
Now I want this delay to go in round robin from 0->....->7->0 and so on, but it should satisfy the condition that it should be present in strm. So I want something like
while (delay not in strm) begin
delay+=1;
end
Other than going though each and every index (2^16-1) is there any other way of finding if it exists in this packed+unpacked array? Thanks in advance!
If you are not aware, you are declaring strm as an associative array (aka a hash), where the key and the data are both 16 bit values.
If you want strm to be a fixed-size 2^16 entry array of 16-bit values, the declaration would be:
bit[15:0] strm [2**16];
With associative arrays you can use array.exists(key) to determine if the key is in the array. But it seems this may not be what you are trying to do.
With unpacked arrays, you can use the inside operator to test for set membership. But my simulator (Incisive) does not like this usage outside of a randomization call. So you may need to search for it yourself. However you don't have to iterate the entire array if you sort it first. And you can do that with array.sort().
I would also point out that you are looking for a 3-bit value in some sort of array of 16-bit values. This doesn't really make sense, so you may want to clarify your question.

Resources