Constructing a Map With Vectors as Values - c++

I am trying to construct a map that maps a string to a vector of unsigned integers. The way that I construct this map is as follows:
void PixelP1ROCDACSettings::getDACs(map<string,vector<unsigned int>>& dacs) const
{
dacs.clear();
dacs.insert(pair<string, vector<unsigned int> > (k_DACName_Vdd, make_vector(Vdd_, k_DACAddress_Vdd)));
dacs.insert(pair<string, vector<unsigned int> > (k_DACName_Vana,make_vector(Vana_, k_DACAddress_Vana)));
...
}
Where make_vector is defined as follows:
std::vector<unsigned int> make_vector(unsigned int DACValue,
unsigned int DACAddress) const ;
My questions are:
1) I would like to get access each individual value in my vector, I've tried to do,
dacs[key][index] but that didn't seem to work. Is there a special syntax to do this?
2) Additionally, I would like to iterate across my map, How would I do that?
Thanks in advance.

If you are using c++11 you can iterate with
for (auto& keyvaluepair : dacs) {
//keyvaluepair.first is your string
//keyvaluepair.second is your vector
}
also dacs[key][index] is the correct way to access the indexth element in the vector mapped to by key.

Related

Making an array of pairs of vectors

I'm trying to make an array of pairs of vectors, and in the vectors is another pair of int and float. Here is the code to help explain: pair<vector<pair<int,float> >, vector<float> >[numNodes];
At first I just had an array of a vector of pairs, but now that I changed it to an array of pairs I'm being thrown errors. I think the errors have to do with the placement of make_pair but I'm not sure.
Here is my code, but first, I little more information on what exactly I'm trying to do with the code. I'm working on a school assignment where the goal is to read in a three files of a graph and store it as an adjacency matrix and adjacency list. Right now I'm working on the list. One file has just the connections, another has the weights of the connections, and the last file has the position values of each node. Then I will search the graphs with different search algorithms. The array of vectors was the adjacency list and all the other data types involved in the pair<vector<pair<int,float> >, vector<float> >[numNodes]; were an attempt to store these variables in the list. I know another way of doing this would be to have a Node object with member variables where I can save the nodeID and position values, but I don't know exactly how this would work in terms of adding it into the list. Also would there be advantages to doing this rather than having everything stored in the list?
class AdjacencyList{
public:
pair<vector<pair<int,float> >, vector<float> > *adjList;
int numNodes;
AdjacencyList(int numNodes){//constructor
this->numNodes = numNodes;
adjList = new pair<vector<pair<int,float> >, vector<float> >[numNodes];
}
void addEdge(int sourceNode, int destNode, float weight, vector<float> posVals){
make_pair(adjList[sourceNode].push_back(make_pair(destNode, weight)), posVals);
}
}
And here is the error I'm being thrown:
main.cpp:71:39: error: no member named 'push_back' in
'std::__1::pair<std::__1::vector<std::__1::pair<int, float>,
std::__1::allocator<std::__1::pair<int, float> > >,
std::__1::vector<float, std::__1::allocator<float> > >'
make_pair(adjList[sourceNode].push_back(make_pair(destNode, weig...
Another Error I'm getting after changing the array of vectors to an array of pairs is this:
no member named 'size' in
'std::__1::pair<std::__1::vector<std::__1::pair<int, float>,
std::__1::allocator<std::__1::pair<int, float> > >,
std::__1::vector<float, std::__1::allocator<float> > >'
return adjList->size();
This size function was working before the change, which makes me think these errors are happening because its recognizing it as a pair now instead of an array. Any ideas on how to fix this?
I have no idea what vector of pairs of vectors of pairs of ints and floats and vectors of floats could possibly in any possible way represent, but anyway you could just assign to the pairs of vectors you want to assign to:
#include <vector>
class AdjacencyList{
public:
std::vector<
std::pair<
std::vector<std::pair<int,float>>,
std::vector<float>
>
> adjList;
int numNodes;
AdjacencyList(int numNodes) :
numNodes(numNodes),
// construct the vector with numNodes default-constructred elements
adjList(numNodes) {
}
void addEdge(int sourceNode, int destNode, float weight, std::vector<float> posVals){
// prefer at() instead of [] for error checking
adjList.at(sourceNode) = std::make_pair(
std::vector<std::pair<int, float>>{
// vector of pairs?? anyway:
std::make_pair(
destNode, weight
)
},
posVals
);
}
};
Do not use raw pointers - use std::vector for managing dynamic array. Your code leaks memory allocated by new.
In the first error thrown, the compiler is complaining about a missing method push_back being called. If you look at it, this makes sense because you are trying to call push_back from a pair variable (which does not have implemented any push_back method). And a similar thing goes with the second error: size() is a valid method for the vector class, but here you are calling it from a pointer pointing to an array (check this question for more info).
Instead of an array of pairs, you could use a vector of pairs, or even a set of pairs:
class AdjacencyList{
public:
vector<pair<vector<pair<int,float> >, vector<float> > > adjList;
int numNodes;
AdjacencyList(int numNodes){//constructor
this->numNodes = numNodes;
// no need to initialize the vector
//adjList = new pair<vector<pair<int,float> >, vector<float> >[numNodes];
}
void addEdge(int sourceNode, int destNode, float weight, vector<float> posVals){
// add the new pair <int, float> to the existent vector for this source node
adjList[sourceNode].first.push_back(make_pair(destNode, weight));
// define second value of the outer pair as the parameter variable posVals?
adjList[sourceNode].second = posVals;
// or you wanted to do this? I don't think so :S
make_pair(adjList[sourceNode].first, posVals);
}
}
You could do the same using an outer set instead of vector, and then you would need to change the push_back(...) for insert(...), so that you obtain the benefits of sets of pairs as well.
Actually, if you need to do it using outer arrays, then your code would be fine but changing your AddEdge function to the one proposed above.
I don't really know which is the desired performance of the code, but if you provide more information about it I might be able to help a bit more.
I think you have some inconsistencies in the type declared and the type being added.
You have declared an array (now does not matter whether it is an array, vector, or set) of pairs of vectors. Whereas on your addEdge function you are creating a pair of None (push_back returns None) and vector. The push_back on its side is adding the pair <int, float> of the first vector of the outer pair to you differently variable defined above.

how to traverse in a unordered_map of unordered_map of unordered_map in c++

I wanted to traverse inside a data structure - unordered_map<int, unordered_map<int, unordered_map<int, int>>> myMap. To further specify I want to get the data elements like ->
myMap[someVal1][someVal2]
{all second elements of this unordered map}
I am aware of the fact that the same could by done by a 3d array however using a 3d array would not be efficient as the data range is huge and the program would end up using far more space than required.I tried using some iterators like unordered_map<int, unordered_map<int, unordered_map<int, int>>>::iterator i, and several other such iterators however it always ends up in some error or the other. Could someone help me in understanding how this map can be traversed ? Thanks in advance!
You could traverse the map with a foreach loop (it needs C++11, I think that won't be a problem), if you don't want to use iterators.
myMap mapMapMap;
for(auto& mapMap : mapMapMap){
for(auto& map : mapMap.second){
for(auto& key_value : map.second){
int key = key_value.first;
int value = key_value.second;
// ....
}
}
}
Also, if you didn't want to iterate all the map, but only the values of the third level, given the two first, then this should make it:
int k1, k2;
for(auto& key_value : myMap.at(k1).at(k2)){
//...
}

How to sort a set of pairs?

How shall I use the qsort function to sort a set of pairs ?
This is my set :
set< pair< int, int> > my_set
This I guess should be my compare function:
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
Should my qsort look like this?
qsort (my_set, no_of_pairs, sizeof(int), compare);
When I sort them I want to sort by the values of a bi-dimensional array **M;, where
M[my_set.first][my_set.second] = the_value
First, prefer std::sort to qsort with c++ std containers.
Secondly, you cannot sort a std::set a posteriori. std::set is sorted.
You can however specify a custom sorting for the std::set at instanciation using a 2nd template parameter.
Refer to the specs.
What you could do, if you need to sort the data after the fact, is use a std::vector instead. There is an algorithm that will cull the duplicate value.
This proposed solution assumes M is some global variable.
#include <algorithm>
bool less_than(const std::pair<int, int> &some, const std::pair<int, int> &other) {
return M[some.first][some.second] < M[other.first][other.second];
}
std::sort(yourvector.begin(), yourvector.end(), less_than);
If M isn't a global variable, you could do something like that :
struc Compair { // see what I did there ? #sofunny
bool operator() (const std::pair<int, int> &some, const std::pair<int, int> &other) {
return M[some.first][some.second] < M[other.first][other.second];
}
int **M;
}
then in main :
Compair mycomparefunctor;
mycomparefunctor.M = arr; // arr is the original int **
std::sort(yourvector.begin(), yourvector.end(), mycomparefunctor);
EDIT :
If you must use a std::set then you should define the custom ordering when you declare it, like so :
Compair mypredicate;
mypredicate.M = arr; // arr is the original int **
std::set<std::pair<int, int>, mypredicate> myset;
// add stuff to the set. They will be sorted following your predicate.
Be careful though : in a set you cannot add 2 items that compare equal. So if your int ** 2D array has several values that are equal, you won't be able to have several pairs corresponding to indexes of equal value in the set.
You're going about this fairly wrong.
Let's assume that we know the maximum value for each member of the pair. If you don't know this, then you need to figure it out. I'm going to assume that it is 100.
Then all we need to do is iterate over the set, and insert them into the new array. There's no faster way to go about this.
int M[100][100] = {};
for (auto const & pair : my_set)
M[pair.first][pair.second] = the_value;

How can I access a specific element in a std::map with more than 2 elements?

I am trying to access a specific element out of a std::map with more than two elements. Here is an example:
std::map <int, CString, CString, CString> map;
//Initialise
map[0] = _T("stuff1"), _T("stuff2"), _T("stuff3");
//now if I just want to access stuff3 is it this:
CString str = map[0][2];
//or something more like this?
CString str = map[0]. ???
Any help would be great thanks.
edit: Thanks sorry about that, first time using maps, I was wondering why I couldn't find any information on std::map 's with more elements inside.
Have you tried to compile this? It shouldn't.
You can create only a map with exactly 1 key and 1 value for each element.
But the value can be compound, so you can write
struct ValueType {
CString v1;
CString v2;
CString v3;
}
std::map <int, ValueType> map;
and access elements like map[somekey].v3;
To insert a value in such a map, you'll have to write
ValueType strings = {"1","2","3"};
map.insert(999, strings);
Or you may create a helper function (i.e. void addToMap(std::map <int, ValueType> &map, CSting const& v1, CString const& v2, CString const& v3) ), which will fill your map in a more convenient way.
std::map <int, CString, CString, CString> map; is illegal.
Either use a std::multimap or a std::map<int,std::vector<CString> >.
I believe this what you are looking for
std::map <int, std::list<CString> > myMap;
then you'll access myMap[0], then access each element in the returned std::list<CString>

C++, Error in Array

I assigned array
char words[100][100];
Now I want to save a word and its pos in the line.
Say line has "hi Iam a programmer". Now I want to save
string word;
while(line){
//called a function to get the word and position.
words[word]["pos"] = pos;
}
I have split the words and saved in the string word, but when I try to save I get error.
"No viable overloaded operator[] for type 'char[100][100]"
What am I doing wrong?
You are trying to use array as a map. You can't use strings as array index. The structure you need is std::map<std::string, std::map<std::string, int> >
std::map<std::string, std::map<std::string, int> > m;
m["foo"]["bar"] = 10;
char[100][100] is a multidimensional array of single characters, which can be used to store fixed-length strings. It can be indexed using integer variables, not strings.
It looks like you want to use std::map<std::string, std::map<std::string, int> > or similar.
You cannot use a string as an index in C++ arrays. What you need is a map:
std::map< std::string, std::map<string, int> > words;
Then you have to:
words[word]["pos"] = pos;
But, what other data would you be saving other than pos? If not, then why do you want to make it a 2 dimensional data structure? Can't you just:
positions[word] = pos;
Where positions is of type std::map<std::string, int>.
EDIT: As pointed out by Mike, not using pointers anymore.