C++ - Multidimensional Arrays - c++

When dealing with multidimensional arrays, is it possible to assign two different variable types to the array...
For example you have the array int example[i][j] is it possible for i and j to be two completely different variable types such as int and string?

Sounds like you're looking for:
std::vector<std::map<std::string, int> > myData1;
or perhaps:
std::map<int, std::map<std::string, int> > myData2;
The first would require you to resize the vector to an appropriate size before using the indexing operators:
myData1.resize(100);
myData1[25]["hello"] = 7;
...while the second would allow you to assign to any element directly (and sparsely):
myData2[25]["hello"] = 7;

No. That's not possible. You may want to look into using the STL map.

No, C++ only allows integer types (ex: int, long, unsigned int, size_t, char) as indexes.
If you want to index by a string, you could try std::map<std::string,mytype> but it gets complicated trying to extend that to two dimensions.

No, but you could use std::maps.

No, you can only use integer types as indices.

No you can't. You could achieve this with std::map though.

Related

Can we make an array containing pairs?

I am new to stl and i came across a question where it is required to store a lot of pairs having same characteristics (like:- (string,int)) together. Can we store pairs in array and if so how? Thanks in advance..
You can try something like:
struct demo
{
string str;
int i;
};
std::array<demo, 5> arr; //for fixed size array of 5 elements
std::vector<demo> vec; //for dynamic size arrays
You want ...
to store a lot of pairs having same characteristics
The terminology is a bit wrong. You want to store many pairs of the same type (not "characteristics").
You could define your own struct as answered by Nipun, or use
std::array<std::pair<std::string,int>, 10> arr;
for an array of 10 pairs of strings and ints.
Spend more time on reading a documentation on standard containers and standard utilities. Perhaps you want some other existing thing (e.g. std::set with std::tuple, maybe with your own comparator).
Templates can (and often should) be combined since they are compositional. Be also aware of the rule of five.

Using a subset of a QVector in a function

How to send a portion of a QVector to a function?
QVector<int> a;
a.append(1);
a.append(2);
a.append(3);
a.append(4);
a.append(5);
Some printing function should print "2 3 4" taking the subset of the vector as an argument.
In R this would be possible using a[2:4].
Is this at all possible?
Note: In the std::vector, it is advised to use the insert function to create a new variable. This is a different insert though than QVector has, and thus I cannot find a recommended method.
I must write at least 30 characters so I can tell you, you should try:
a.mid(1,3);
You could always write a function to do this operation for you, e.g.
QVector<int> sub_vector(const QVector<int>& vec, size_t from, size_t to)
{
QVector<int> subvec;
for (size_t i = from; i <= to; ++i)
subvec.append(vec[i]);
return subvec;
}
Yes it is possible, but you must pass a pair of iterators (begin and end of the range you want, you can use std::pair to pass only one argument or use a clearer method that take two QVector::iterator arguments and that way it's clearer that you meant that function to take a range) or if it's simpler to you (or the elements you want are not in continuous order in original QVector) construct another QVector that contains only the selected elements (kind of the solution proposed by john).

Create a dynamic bitset in standard C++?

I feel like I'm just hoping that they can, but can a vector access bitset member functions?
For instance, can I do something like.
vector<bool> myvector;
myvector.count();
myvector.test(1);
If not is there anyway to make a bitset dynamically using the standard C++ libraries?
EDIT:
I want to use certain bitset functions (test, count) and want to use the constructor bitset (unsigned long val).
Basically I want to create a bitset for some arbitrary val then do some operations with test and count. Then I want to deallocate and recreate the bitset with a decremented val. I want to keep doing this until val is less than 8.
However, it doesn't seem like creating a dynamic bitset is possible and using vector which is dynamic, means I can use some of the nice bitset functions.
I have already answered to similar questions in S.O. I would suggest BITSCAN, a framework for dynamic bitsets specially oriented for fast bitscanning. It has been tested on Linux and Windows. A comparison with STL bitset and Boost's dynamic_bitset is available here.
Sounds like you don't actualy need a dynamic bitset. std::bitset is copy-assignable so you can do:
const size_t size = sizeof(unsigned long) * CHAR_BIT;
typedef std::bitset<size> my_bitset;
unsigned long val = 42;
my_bitset bs(val);
/* do work */
bs = my_bitset(--val); // assign with new, decremented val

Efficient ways to lookup values by 3 int

I have a some data that needs to be stored and looked up efficiently. Preferably using C.
Each line of the data file is in the following format:
key1 key2 key3 data
where key1, key2, key3 are integers and data is an array of float.
I am thinking about converting key1,2,3 into a string, then use C++ std::map to map string to a float pointer:
std::map<string, float*>
Are there better ways of doing it?
Note: integer key1,2,3 has a range of 0-4000, but very sparsely populated. In another word if you go through all the values in key1, you will find < 100 unique int within the rang eof 0-4000.
You can use std::tuple to combine the three values into one:
std::map<std::tuple<int, int, int>, float *>
you do not have to use strings if your data limits for each key is from 0 to 4000
first generate the combined key as follows:
unsigned long ulCombinedKey = key1 + key2<<12 + key3 <<24;
after that you can use the map as you already stated in your questions.
A hierarchical map would do it:
map<int, map<int , map<int, list<float> > > > records;
and the access time would be good (logarithmic).
This way would be efficient if the range is very wide. Otherwise for 4000 the suggested shifts given in previous answer is faster and more efficient.
A hash provides very fast access to data, so you might want to use hashes to look up values from each of the three integers. This approach can be used in either c or c++.
For each line of data:
1. allocate space for the array of floats
2. store a pointer to the array of floats in an array of pointers
3. store the index of the pointer array in a hash based on on int1
4. store the index of the pointer array in a hash based on on int2
5. store the index of the pointer array in a hash based on on int3
This way, given int1, int2, or int3, one could look up a pointer array index, retrieve the pointer, then follow the pointer to the array of floats. This approach uses some memory, but not too much, given the problem said there are < 100 unique values for each of int1, int2, and int3.

Increase values in map

I have a map of key-value pairs. A priori I don't know it's size, i.e. how many and which keys I will have. Now, within a look, the keys "appear" and I need to increase the value for the corresponding key, each time it appears.
Example:
std::map<int, unsigned int> myMap;
std::vector<int> vectorOfValues; // 123,456,123,789,123,456
for(unsigned int i=0; i<vectorOfValues.size(); ++i) {
myMap[vectorOfValues.at(i)] += 1;
}
So now myMap should contain <123,3>, <456,2>, <789,1>.
Question:
Is this the correct? I'm afraid the using the map without initialising the values isn't a good idea. But I'd like avoid to search for the entry each time I want to increase it.
Cheers!
IMO, it's fine, the unsigned int will be default constructed (i.e. zero initialized), one comment is that the at() call is superfluous - use the operator[] (as you already constrain by size()).
This is correct; previously non-existing values will be initialized to zero.