Accessing elements of a vector in a map of vectors - c++

I want to create a map of vectors. I want the vector to be a private member variable however so when I need to increase the size of the vector for a particular key in the map it does it for all other keys in the map also(would that work?). This will be a map of vectors(of ints) where the keys are strings. My question is how to access a particular element in the vector to change is value in C++. Something along the lines of map_name['word'].[3] = 2 if i wanted to set the third value of the vector of "word" to 2.
enter image description here
enter image description here
Im still having trouble figuring out how to make it so the size of each vector for all the keys in the maps is modifiable so i can increase the size of each vector at any point along the program. This is b/c the vector size is unknown at runtime and iterating through each element in the map to change the vector size will take too long.

The pattern is recursive.
That is, when you do:
expression[key] = value;
your expression doesn't have to just be a variable name; it can be a more complex expression, such as map_name["word"].
So:
map_name["word"][3] = 2;

Regarding the first question, yes it is possible as mentioned in one of the comments, you can make your imaginary class to do that.
And in the second question, you'll have to access an element of a vector which is an element of a map like this:
map1["abc"][1] = 2
The '.' you added was unnecessary because you're accessing an element inside another element, just like a 2D array

Related

How to retrieve a value from a vector of vectors?

I am trying to make a vector that contains vectors, that contains a string. I am unsure on how I would go about retrieving said string. I've tried vector.at() but I'm not sure how to make a sort of 'multi-layered' version of it.
This is the value inside of my code:
std::vector<std::vector<std::string>> dialoguestore;
There are many ways to go about this with a 2D vector.
Option 1: at():
dialoguestore.at(index).at(index2);
Option 2: operator[]:
dialoguestore[index][index2]
If you have a multidimensional vector, use the ways you normally access a vector, but for the number of dimensions.

C++ : How can I push values into a vector only if that value isn't stored in the vector already?

If for example, I was just pushing 200 random numbers into a vector, how can I ensure that duplicates will not be pushed in?
seems like a map could be a helpful structure instead of a Vector.
If you must stick to a Vector then you need to divide your task into two parts; duplication detection and then insertion. Again, your could insert into a map and then read that out into the Vector.
In either case the problem is - intrinsically - two problems. Good luck!
You need to check if the vector already contains the value, if not the push new value, i.e.
std::vector<int>::iterator it;
it = find (myvector.begin(), myvector.end(), newvalue);
if (it == myvector.end()) {
// newvalue is not found
}
But this could be costly since find method would be checking every value inside myvector.
Instead using set or map data structure can be more efficient.
If the random numbers are integer and within a relatively small range, you can try this:
You want N unique random numbers from M possible values whereby M >= N
create a container containing one of each of the unique random number
shuffle the container
take the first N from the container and insert to your vector
If M is much bigger than N (like between 0 and rand_max), then you should just check for repetition before insert and repeat until your container size reaches 200. If using vector is not mandatory, I will suggest using std::set instead since it ensures unique values by default.

2D Dynamic Array, using two data types?

I've searched around the internet, and I can't seem to find the answer to my solution (or I'm blind/dumb and just can't figure out how to do it). Part of one of my assignments is as follows:
Constructor – creates an empty 2xn dynamic array. Your dynamic array should start as 2x5 in size but can grow to any length. The default value for empty `elements is “empty” and 0. The class should also have a nextElement variable that keeps track of the next empty spot in the array and is increment each time a data element is added.
Is there a way to create a 2*5 array that will accept string in one of the dimensions and integers in the other?

Redundant static data

This question applies to any type of static data. I'm only using int to keep the example simple.
I am reading in a large XML data file containing ints and storing them in a vector<int>. For the particular data I'm using, it's very common for the same value to be repeated consecutively many times.
<Node value="4" count="4000">
The count attribute means that the value is to be repeated x number of times:
for(int i = 0; i < 4000; i++)
vec.push_back(4);
It seems like a waste of memory to store the same value repeatedly when I already know that it is going to appear 4000 times in a row. However, I need to be able to index into the vector at any point.
For larger data objects, I know that I can just store a pointers but that would still involve storing 4000 identical pointers in the example above.
Is there any type of strategy to deal with an issue like this?
Use two vectors. The first vector contains the indices, the second one the actual values.
Fill in the indices vector such that the value for all indices between indices[i-1] and indices [i] is in values[i].
Then use binary search on the indices array to locate the position in the values array. Binary search is very efficient (O(log n)), and you will only use a fraction of the memory compared to the original approach.
If you assume the following data:
4000 ints with value "4"
followed by 200 ints with value "3"
followed by 5000 ints with value "10"
You would create an index vector and value vector and fill it like this:
indices = {4000, 4200, 9200}; // indices[i+1] = indices [i] + new_count or 0
values = {4,3,10};
As suggested in the other answers, you should probably wrap this in an operator[].
I would suggest to write a specific class instead of using vector.
Your class should just hold the number of times an item occurs in a list and compute the index in a smart way so you can easily retrieve an element based on the index.
Try to wrap your data into some objects with vector-like interface (operator[] and so on), so you can hide implementation detail (that is you are not actually storing 4000 numbers) yet provide similar interface.

Merging two arrays of a class

I have two arrays of class Record. Class Record is defined like this
class Record{
char* string; //the word string
int count; //frequency word appears
}
And these are the two arrays defined (already initialized)
Record recordarray1=new Record[9000000]; //contains 9000000 unsorted Records
Record recordarray2=new Record[8000000] //contains 8000000 unsorted Records
the purpose is to find strings that match between the two arrays and add them to a new array where their counts are added together, and if there is a string not in the other array then just add to the new array. To do this I have tried sorting the two arrays first, (in alphabetical order by strings), then comparing recordarray2, if the string matches then advance recordarray2's index otherwise advance recordarray1's index until you find one. If you don't find it, then add it to the new array.
Unfortunately this method is WAY too slow, sorting itself takes 20+ seconds with STL sort. Is there a quicker standard method of sorting that i'm missing?
If I've understood correctly your algorithm should take O( nlogn + mlogm [sort both arrays] + n + m [to go through the arrays and compare]).
It may not be much of an optimization but you try to sort just one of the arrays and use binary search to check if the elements of the other array are present or not. So now it should take O( n [to copy one array as the new array] + nlogn [to sort it] + mlogn [to binary search the elements of the second into the sorted new one] ).
HTH
Sorting object might be expensive, so I would try to avoid this.
One faster way might be to create an index for each array using a std::hash_map with the string as has index and the array index as value. You get two containers that can be iterated at one time. The iterator for the lesser will be advanced until you find a match or the other points to a lesser value. This will lead you to a predictable iteration count.
The possible solution is to use unordered_map. The algorithm whould be as following:
Put the first array into the map, using strings as keys and count as values.
For each member in the second array, check it against containment in the map.
If it exists there
Put the record into the new array, combining counts
Remove the record from the map
Else
Put the record into the new array
Iterate throug the remaining recors in the map and put the in to the new array.
The complexity of this algorithm is aproximatelty O(n+m)
I feel that sorting is not needed. You can use following algorithm.
Start with the first element of
recordarray1; put into the new array
Search elements in recordarray2.
If the element is found increment count in new array. Also set the
recordarray2[N]::count to negative value; so that it will not be checked again in step 3
Put all the elements from
recordarray2 which doesn't have
count set to negative into new
array. If negative count is
encountered then simply change it to
positive.
Note: This algorithm doesn't take care if you have similar string elements in the same array. Also don't use string as a variable name. As it's also a typename as std::string.