Insertion in maps in C++ - c++

map<string ,vector<string> > hashes;
hashes.insert(pair<string,vector<string> > (a,b )); //error coming
What is the problem coming when i am using the above statement in C++, where a and b are strings?
How does the insertion takes place in this type (i.e. one container containing more container) of associative container?
Many many thanx in advance

You probably want
hashes[a].push_back(b)
That's if you want b to be appended to the present vector. If you want it to replace it, use
hashes[a].assign(1, b)

You're trying to use a string where a vector of string is needed. You need to insert b into a vector, then insert (a, your_vector) into the map.
Alternatively, use a multimap<string, string> to get the same basic effect in a way you may find easier to use. This would allow your insert(pair<...>(a, b)).
Also consider using std::make_pair instead of instantiating std::pair directly. It'll deduce the types for the arguments so you don't need to fill them out explicitly.

Just follow the definition:
vector<string> v;
v.push_back("mystring");
hashes.insert(std::make_pair("key", v));
Note how the second parameter to make_pair is a vector<string>. This will never fail then. It will fail if the second parameter is a string.

Related

C++ Table of Vectors of Different Types

I have a collection of vectors of different types like this:
std::vector<int> a_values;
std::vector<float> b_values;
std::vector<std::string> c_values;
Everytime i get a new value for a, b and c I want to push those to their respective vectors a_values, b_values and c_values.
I want to do this in the most generic way possible, ideally in a way I can iterate over the vectors. So I want a function addValue(...) which automatically calls the respective push_back() on each vector. If I add a new vector d_values I only want to have to specify it in one place.
The first answer to this post https://softwareengineering.stackexchange.com/questions/311415/designing-an-in-memory-table-in-c seems relevant, but I want to easily get the vector out for a given name, without having to manually cast to a particular type. ie. I want to call getValues("d") which will give me the underlying std::vector.
Does anyone have a basic example of a collection class that does this?
This idea can be achieved with the heterogenous container tuple, which will allow for storage of vectors containing elements of different types.
In particular, we can define a simple data structure as follows
template <typename ...Ts>
using vector_tuple = std::tuple<std::vector<Ts>...>;
In the initial case, of the provided example, the three vectors a_values, b_values, c_values, simply corresponds to the type vector_tuple<int, float, std::string>. Adding an additional vector simply requires adding an additional type to our collection.
Indexing into our new collection is simple too, given the collection
vector_tuple<int, float, std::string> my_vec_tup;
we have the following methods for extracting a_values, b_values and c_values
auto const &a_values = std::get<0>(my_vec_tup);
auto const &b_values = std::get<1>(my_vec_tup);
auto const &c_values = std::get<2>(my_vec_tup);
Note that the tuple container is indexed at compile-time, which is excellent if you know the intended size at compile-time, but will be unsuitable otherwise.
In the description of the problem that has been provided, the number of vectors does appear to be decided at compile-time and the naming convention appears to be arbitrary and constant (i.e., the index of the vectors won't need to be changed at runtime). Hence, a tuple of vectors seems to be a suitable solution, if you associate each name with an integer index.
As for the second part of the question (i.e., iterating over each vector), if you're using C++17, the great news is that you can simply use the std::apply function to do so: https://en.cppreference.com/w/cpp/utility/apply
All that is required is to pass a function which takes a vector (you may wish to define appropriate overloading to handle each container separately), and your tuple to std::apply.
However, for earlier versions of C++, you'll need to implement your own for_each function. This problem has fortunately already been solved: How can you iterate over the elements of an std::tuple?

C++ Make a banlist with std::vector or std::map

I am trying to write a small banlist with std::vector/std::map. But i don't know how it should work yet...
Here is how "BanList" is build on Networking.h:
static std::vector<int, std::string>BanList;
Int is for the ID
string for the target IP
This is a snippet of my Networking.cpp (Where the target gets added to the banlist)
if (boost::contains(dataPackage.data, needle1) && boost::contains(dataPackage.data, needle2))
{
// All okay here - Let's jump over & let the thread handle the action
}
else
{
//e.g. BanList.addTarget(Auto-Incremented ID, TargetsIP);
break;
}
So there on the line where's // e.g BanList.addTarget(int, string); how should it work with std::vector or std::map? How can i create now a list full of the targets? To get the IP is not my problem! The problem is how to set the ID automatically and add then the target to the list... Already now thank you for your help.
I'm not quite sure what your question is here. If you want to know how to use maps, then you should see the the online reference.
In your particular case, if you use the map:
static std::map<int, std::string> banList;
banList[id] = ipAddress;
I don't know why you would want to map ints to strings for a ban list. But this is how you do it.
For a vector, you can't have key/value pairs unless you're pushing a std::pair object. For that though, you almost always will want to use a map.
To add to a vector, use vec.push_back(item).
You can find almost all of this on online references.
Carefuly read the std::vector's template parameters. std::string is not a valid allocator for int :)
This would be closer to std::map<int, std::string>:
std::vector<std::pair<int, std::string>> BanList;
Learn the rest about std::vector/std::pair or std::map from the reference/your favorite book. It isn't worth explaining it here (and there is not enough space for it).
If TargetsIP is something like std::vector<std::string>, you will need to iterate through it and append elements to BanList in a loop.

Insertion into pair that is mapped value in multimap in C++

Found this Multimap containing pairs?, but it is not much help
How would I insert two strings into pair? Below, my two failed attempts.
multimap<string, pair<string,string> > mymm;
mymm["Alex"] = std::pair<"000","000">; //errors
mymm.insert(pair<string, pair<string, string> >
("Alex", std::pair<"000","000">); // errors out as well
I am using Visual Studio 2010, 32 bit. Thanks !
mymm.insert(make_pair("Alex",make_pair("000","000")));
A multimap doesn't allow lookup using operator [], since there may be more than one match.
make_pair is a convenient way to create a pair without having to specify the types explicitly. Without using make_pair, you would need to do something like this:
mymm.insert(pair<string,pair<string,string> >("Alex",pair<string,string>("000","000")));
std::pair<string,string>("000","000") should do it.
The code contained between < and > indicates the types of the variables you're inserting-- in this case strings

Easy way to make vector triplet in CPP

What would be an easy way to construct a vector triplet of ints in CPP?
i.e instead of a pair of 2 ints ,
std::vector<std::pair<int, int> > vec;
I want 3 int's tied together as one element of the vector.
I realized one way would be to make 2 sub-nested pairs, but this method gets messy. I am not aware of all the details of CPP, therefore please recommend an easier way if available. Thank you.
std::vector<std::tuple<int,int,int>> myvec;
No need to over-engineer.
struct Triplet
{
int one_, two_, three_;
};
vector<Triplet> triplets;
Check out boost tuple http://www.boost.org/doc/libs/1_49_0/libs/tuple/doc/tuple_users_guide.html
You can easily create Pairs, triples, quadruples, up to n-uples!
In C++11, there is std::array, see here. In C++03, I would probably define a struct of 3 ints and make a vector of those.

Using map containing set as a value

Basically I have,
typedef map<std::string, set<double> > MAP_STRING_TO_SET;
What is the best way to update (add or remove value) the set with a new value without causing the set to be copied?
The only viable solution I see is to use map<std::string, set<double>* > -- something I don't want to do.
Thanks
The set is only copied in initialization.
You are allowed to do something like
myMap[myString].insert(myDouble);
since map::operator[] returns a reference.
You can also do this:
map<std::string, set<double> >::iterator iter = myMap.find(myString);
if(iter != myMap.end())
{
iter->second.insert(myDouble);
}
I think you can just use swap - eg.
my_map["123"].swap(my_set)
provided clobbering my_set doesn't matter to you. This would swap the previous contents of my_map["123"] with my_set, and it's fast.
The indexing operator[] returns a reference to the contained set - therefore, you can manipulate it just like any other variable. If you want to add/remove individual values, you can just use insert() or erase() methods - eg. my_map["123"].insert(123).
The copying actually takes place when you assign a new set to the map - eg.
my_map["123"]=my_set
would create a copy of my_set. If you don't need to use the value of my_set later, you can use the swap() method, which will just shuffle pointers of the two sets. my_set will, however, have the contents of the previous my_map["123"].