Can you please tell me how I can write multidimensional map. For two dimensional map, I did the following:
map<string, int> Employees
Employees[“person1”] = 200;
I was trying to use something similar to following for 3d mapping.
map<string, string, int> Employees;
Employees[“person1”, “age”] = 200;
Can you please tell me the correct way to do this?
and Is there a way I can initialize all the map elements to be 0 ? Just like on a array we can say int array[10]={0};
You need to create map of maps like that.
map<string, map<string, int> > employees;
employees["person1"]["age"] = 200;
You can use the pair class of the utility library to combine two objects:
map<pair<string, string>, int> Employees;
Employees[make_pair("person1", "age")] = 200;
See http://www.cplusplus.com/reference/std/utility/pair/
Instead of nested map, you can use tuple as keys; (this is a c++11 code, you could do the same with boost::tuple as well).
#include<map>
#include<tuple>
#include<string>
using namespace std;
map<tuple<string,string>,int> m;
int main(){
m[make_tuple("person1","age")]=33;
}
what you are doing here is not 3D mapping but 2D mapping, how to use stl::map as two dimension array
Correct 3D mapping will be like
map<string, map<string, map<int, string> > > Employees;
Employees[“person1”][“age”][20] = "26/10/2014";
Related
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.
I've been shown how to create a jagged multidimensional std::map by using boost::any.
However, I'm having trouble setting the values like in this answer.
When I use
accounts["bank"]["cash"] = 100;
gcc gives this error
error: no match for ‘operator[]’ in ‘accounts.std::map<_Key, _Tp, _Compare,
_Alloc>::operator[]<std::basic_string<char>, boost::any,
std::less<std::basic_string<char> >, std::allocator<std::pair<const
std::basic_string<char>, boost::any> > >((* & std::basic_string<char>(((const
char*)"bank"), (*(const std::allocator<char>*)(& std::allocator<char>())))))["cash"]’
How can a jagged multidimensional map created with boost::any be accessed? (If there is a better technique to do this, please show me. I only care about what works and is quick to write.)
multidimensional declaration
std::map<std::string, boost::any> accounts;
accounts["bank"] = std::map<std::string, boost::any>();
accounts["bank"]["cash"] = 100;
json-spirit
I gave up and tried to use json-spirit's mObject instead since all of this seems already built in.
Funny thing is is that with the exact same notation, I get the exact same error.
std::map<std::string, boost::any> accounts;
accounts["bank"] = std::map<std::string, boost::any>();
accounts["bank"]["cash"] = 100;
Of course this cause compile time error, you put to boost::any std::map,
but compiler have no idea about this. accounts["bank"] has "boost::any" type,
and boost::any have no
int& operator[](const char *)
Read how boost::any works: http://www.boost.org/doc/libs/1_54_0/doc/html/any/s02.html
Fix is trivial:
#include <boost/any.hpp>
#include <map>
#include <string>
int main()
{
std::map<std::string, boost::any> accounts;
accounts["cash"] = 100;
accounts["bank"] = std::map<std::string, boost::any>();
boost::any_cast<std::map<std::string, boost::any> &>(accounts["bank"])["cash"] = 100;
}
How did you define your accounts map? As boris said, you need to nest two maps together in order to do what you want.
Replace the type string with boost::any
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, map<string, string>> accounts;
accounts["bank"]["cash"] = "infinity";
cout << accounts["bank"]["cash"];
return 0;
}
How does this work?
Maps are key and value pairs.
accounts["bank"] returns the value of the outermost map, which corresponds to
map<string, **map<string, string>**>
accounts["bank"]["cash"] returns the value of the innermost map, which corresponds to
map<string, map<string, **string**>>
Defining a 1 dimensional map does not allow you to do what you want, but 2 dimensional maps do.
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.
SKU1 SKU2 Description
"01234" "34545" "White Bread"
"01545" "34236" "Wheat Bread"
I need to cross-reference these three fields, i.e. retrieve SKU2 while knowing SKU1, SKU1 while knowing SKU2, and Description while knowing either SKU1 or SKU2.
I'm curious - what is the best way to do this? Vectors using search() or find()? Using a map somehow?
I currently have it working using a vector< vector<string> >, looping through the 'parent' vectors and the 'child' vectors, comparing the values, but this seems primitive.
Basically, I need a vector that uses any of its strings as an index to return one of the two other values. Is the general way I'm doing it considered acceptable/optimal?
vector< vector<string> > products;
int i = 0;
for( i = 0; i < 2; ++i)
{
products.push_back( vector<string>() );
products[i].push_back( "SKU1" );
products[i].push_back( "SKU2" );
products[i].push_back( "Description" );
}
Thanks for your assistance.
Boost BiMap.
I would recommend using two maps that index into an object that has the information you need:
struct MyInfo
{
std::string SKU1;
std::string SKU2;
std::string Description;
};
std::map<std::string, MyInfo *> SKU1map;
std::map<std::string, MyInfo *> SKU2map;
MyInfo * newProduct = new MyInfo; ///Do not forget to delete!!
newProduct->SKU1 = //SKU1 value
newProduct->SKU2 = //SKU2 value
newProduct->Description = //Description value
SKU1map[newProduct->SKU1] = newProduct;
SKU2map[newProduct->SKU2] = newProduct;
This will be a decently fast implementation(much better than linear search), and if you deal with many product instances, then it will also be more memory efficient.
Build three std::map<std::string, std::string>s: one to map SKU1s to SKU2s, one to map SKU1s to Descriptions, and one to map SKU2s to Descriptions. (Better yet, use std::unordered_map, if you have it (C++0x)).
This is assuming that you have a lot of data and are prioritizing speed rather than memory usage.
I am trying to make a 5 dimensional vector and I can’t seem to get it to work.
I know if I need to write a 3 dimensional vector, I could write it in the following way:
vector< vector< vector<string> > > block(27, vector< vector<string> > (27, vector<string>(27)));
Then I call it: block[x][y][z] = “hello”;
I wrote the 5 dimensional vector in the following way and it gives me error.
vector< vector< vector< vector< vector<string> > > > > block(27, vector< vector< vector< vector<string> > > >(27, vector< vector< vector<string> > >(27, vector< vector<string> >(27, vector<string>(27)))));
Can you please tell me how to write a 5 dimensional vector in the right way?
Thanks a lot.
The final vector in your 5 dimensional array does not have a type that it is an array of.
vector< vector< vector< vector< vector > > > >
^^
Here. What is the base vector a vector off?
To make things easy to read a couple of typedefs would be nice:
typedef std::vector<std::string> Dim1;
typedef std::vector<Dim1> Dim2;
typedef std::vector<Dim2> Dim3;
typedef std::vector<Dim3> Dim4;
typedef std::vector<Dim4> Dim5;
Dim5 block(27, Dim4(27, Dim3(27, Dim2(27, Dim1(27)))));
Consider using the Boost Multidimensional Array Library for higher dimensional arrays.
http://www.boost.org/doc/libs/1_43_0/libs/multi_array/doc/user.html
"Boost MultiArray is a more efficient and convenient way to express N-dimensional arrays than existing alternatives (especially the std::vector> formulation of N-dimensional arrays). The arrays provided by the library may be accessed using the familiar syntax of native C++ arrays. Additional features, such as resizing, reshaping, and creating views are available (and described below)."
But you should stop and think if a dictionary would work better. If the data is sparse you'll save a ton of memory.
Create a key using the 5 dimensions, and create only the members you need.