c++ map finding value and associated key - c++

I develop one program in c++ in which i have to find key in stl map by using values.
But values assigned to key is the 5 tuples (srcip,port,destip,port,srcno)
Now i want to check in map whether there is key assosiated with values.
I am trying something like this.
But its showing error like
wrong number of template argument.
Note(In my program in pair key->Value) value consist of tuple of 5 variable.
template<class T>
struct map_data_compare : public std::binary_function<typename T::value_type,typename T::mapped_type,bool>
{
public:
bool operator() (typename T::value_type &pair,typename T::mapped_type i)
{
return pair.second == i;
}
}
class Values
{
private:
std::string C_addr;
int C_port;
std::string S_addr;
int S_port;
int C_ID;
public:
Values(std::string,int,std::string,int,int);
void printValues();
};
Values :: Values(std::string Caddr,int Cport,std::string Saddr,int Sport,int Cid)
{
C_addr=Caddr;
C_port=Cport;
S_addr=Saddr;
S_port=Sport;
C_ID=Cid;
}
void Values::printValues()
{
cout << C_addr<<":" <<C_port<<":" << S_addr <<":" <<S_port << ":"<<C_ID <<endl;
}
//In main
{
typedef std::map<int, Values> itemsType;
itemsType items;
Values connection (inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port),inet_ntoa(servaddr.sin_addr),ntohs(servaddr.sin_port),clientID);
std::map<std::int,Values>::iterator it = std::find_if( items.begin(), items.end(), std::bind2nd(map_data_compare<itemsType>(),connection));
if ( it != items.end() )
{
assert( connection == it->second);
std::cout << "Found index:" << it->first << " for values:" << it->second << std::endl;
}
else
{
std::cout << "Did not find index for values:" << connection <<endl;
}

I develop one program in c++ in which i have to find key in stl map by using values.
That's not what maps are meant for. If you need that kind of access, I recommend Boost.Bimap

If the 'key' must be unique, maybe you can try combine the key and value into a std::pair and push them into std::set.
Otherwise you should set your key as value and value as key since you seems mainly use your original value as what we treat to a "key". Then you could use the built-in map::find() function

Related

Why is this unordered_map not finding existing keys? (C++14)

I'm trying to use an unordered_map for a custom type. However, the map is storing duplicate entries, which have the same hash value and should evaluate as equal when using ==.
I've reduced my code to the following proof of concept, where I can see that the hash function runs correctly, but the equals operator is never called.
#include <unordered_map>
// Define a class with a single integer member.
class Example
{
public: int x;
public: Example(int x)
{
this->x = x;
}
// Overload == and compare the single member.
public: bool operator==(const Example &other) const
{
std::cout << "Comparing two objects\n";
return this->x == other.x;
}
};
// Define a hash function class
class ExampleHash
{
public: size_t operator()(const Example* key) const
{
// simply return the member variable as the hash value.
std::cout << "Returning hash value " << key->x << "\n";
return key->x;
}
};
int main()
{
// Create an empty map.
std::unordered_map<Example*, int, ExampleHash> m;
std::cout << "Inserting a new key\n";
// Insert an object with the value 1.
m[new Example(1)] = 1;
std::cout << "Existing hashes:\n";
ExampleHash fn;
for (auto const &item : m) {
size_t h = fn(item.first);
std::cout << " " << h << ", ";
}
std::cout << "\n";
std::cout << "Finding the key\n";
// Check if the object is in the map.
std::cout << ((m.find(new Example(1)) != m.end()) ? "Found" : "Not found") << "\n";
}
Output:
Inserting a new key
Returning hash value 1
Existing hashes:
Returning hash value 1
1,
Finding the key
Returning hash value 1
Not found
(Note the absence of the "Comparing two objects" line when calling unordered_map::find, despite the hash value clearly being in the map already.)
Pointers are not the objects they point to.
You are using pointers as keys. The objects equal operator will be ignored.

Find unique values in map<string, vector<string>>?

I'm trying to create a basic search function. Right now, I have the function to set up to accept three arguments: map<string, vector<string>>, const string& key, and bool unique.
My goal is to have query check if key is in the map, and if it is with bool unique = false just output all the values associated with the key, duplicates and all.
However, I need to also have the ability to output just the unique values associated with the key if bool unique = true
I have the latter part working exactly as a want it, but I'm struggling with outputting the unique values. How do I go about this? Is it possible to do so without creating a new vector or altering the map?
Apologies if anything is unclear, I'm happy to clarify if needed. Thank you.
void query(const map<string, vector<string>>& map, const string& key, bool unique) {
const auto pair = map.equal_range(key);
if(map.count(key)){
for( auto iter = pair.first ; iter != pair.second ; ++iter ){
for( const auto& str : iter->second ) {
if (!unique){
cout << " " << key << " ";
cout << str << "\n";
} else if (unique) {
// output key + unique values
}
}
}
} else {
cout << "<Not found>\n";
}

Iterating in to the set of strings which are the values in map

#include <iostream>
using namespace std;
void insertValue(map<string, set<string> >& myMap,
string const& key,
string const& value)
{
// Check whether there is already a set given the key.
// If so, insert to the existing set.
// Otherwise, create a set and add it to the map.
map<string, set<string> >::iterator found = myMap.find(key);
if (found != myMap.end())
{
cout << "Adding '" << value << "' to an existing set of " << key << "s.\n";
found->second.insert(value);
}
else
{
cout << "Adding '" << value << "' to a new set of " << key << "s.\n";
set<string> temp;
temp.insert(value);
myMap.insert(make_pair(key, temp));
}
}
int main()
{
map<string, set<string> > filemap;
insertValue(mymap, "file1", "path1");
insertValue(mymap, "file1", "path2");
insertValue(mymap, "file1", "path3");
insertValue(mymap, "file2", "path1");
insertValue(mymap, "file3", "path2");
return 0;
}
Can anyone tell me how I can iterate through the set of strings, given a key in the above map???? or do I have to place an iterator in the value ....I can't understand how can I go this this further
The easiest way to iterate over the map is by using a range-based for instead of using iterators
for(auto const& kv : mymap) {
for(auto const& v : kv.second) {
std::cout << kv.first << ": " << v << '\n';
}
}
kv is a const& to your map's value_type, which is std::pair<const std::string, std::set<std::string>>. The nested for statement is then iterating over the second element in the pair.
And if you really want to use iterators, then use this
for(auto miter = mymap.cbegin(); miter != mymap.cend(); ++miter) {
for(auto siter = miter->second.cbegin(); siter != miter->second.cend(); ++siter) {
std::cout << miter->first << ": " << *siter << '\n';
}
}
That aside, your function for inserting values can be simplified quite a bit. There's no need to check whether an element already exists in a map before inserting a value because map::operator[] will construct the key you pass to it if one doesn't already exist, and the corresponding value type will be value initialized. So your insertValue function becomes a one-liner.
void insertValue(map<string, set<string> >& myMap,
string const& key,
string const& value)
{
myMap[key].insert(value); // default construct a set for a new key
}
Finally, unless you need the values corresponding to a key be ordered, you can use a multimap instead. This container is just like a map, but you can have several values corresponding to a single key value. However, unlike your solution, the order of the values which have identical keys is the order of their insertion.
Live demo

Implementation of stl map in c++ using class of values

I have to develop stl map in which key is integer where value associated with key is 5 tuple.
having integer data types only.
e.g key=1
value=(2,3,4,5,6)
key=2
value=(1,2,3,4,5)
and so on.
how i can implement it for insert and search operation.
mean how to map single key value to tuple of 5 values.
how to accomplish it?
Depending on what your data means I would go for a different approach.
If your values logically belong together, that is if they only make sense in combination, then I would simply store them in a common data structure and store this data structure in a map. For this purpose a class, struct or container might suit your needs. Again it depends on your context what is the best choice.
If your values exist in isolation and the only connection between them is that they share the same key, then I would use std::multimap.
If you have access to C++11, you can make use of std::tuple (or boost´s tuple), which I believe is the best fit data structure to your case. See the snippet below and see if it fits:
#include<tuple>
#include<map>
#include<iostream>
#include<stdexcept>
typedef std::tuple<int, int, int, int, int > fiveIntTuple;
void insert(std::map<int, fiveIntTuple>& values,
int key, int a, int b, int c, int d, int e){
values[key] = std::make_tuple(a,b,c,d,e);
}
fiveIntTuple search(const std::map<int, fiveIntTuple >& values, int key ){
return values.at(key);
}
void print(const std::map<int, fiveIntTuple >& values, int key){
try{
fiveIntTuple t;
t = search(values, key);
std::cout << "For key == " << key << " got: "
<< std::get<0>(t) << ","
<< std::get<1>(t) << ","
<< std::get<2>(t) << ","
<< std::get<3>(t) << ","
<< std::get<4>(t) << std::endl;
}catch(const std::out_of_range&){
std::cerr << "For key " << key << " ... not found" << std::endl;
}
}
int main(){
std::map<int, fiveIntTuple > my_values;
insert(my_values, 1, 2,3,4,5,6);
insert(my_values, 2, 1,2,3,4,5);
print(my_values, 1);
print(my_values, 2);
print(my_values, 3);
return 0;
}
Executing this snippet you must get:
For key == 1 got: 2,3,4,5,6
For key == 2 got: 1,2,3,4,5
For key 3 ... not found

Two dimensional unordered_map

typedef boost::unordered_map<int, void*> OneDimentionalNodes;
typedef boost::unordered_map<int, OneDimentionalNodes> TwoDimentionalNodes;
TwoDimentionalNodes nodes;
is this valid?
i don't use any hash functions since keys of the unordered_maps' are single integers.
it compiles, but when i iterate it like this, it crashes while trying to access this->hash_function()(k);
for (TwoDimentionalNodes::iterator it= nodes.begin(); it != nodes.end() ; ++it)
{
for(OneDimentionalNodes::iterator it2 = nodes[it->first].begin(); it2 != nodes[it->first].end() ; ++it2)
{
// do stuff
}
}
i'm also open to other containers with
O(1) access
O(n) iteration
Sparse
If you just need to iterator over all elements, and it is not required to loop over a specific dimension, then you could use a simple pair as key for your unordered_map, like this:
typedef std::pair<int,int> Coordinates;
typedef std::unordered_map<Coordinates,void *> TwoDimensionalNodes;
(notice I used STL instead of Boost, unordered_map is now also part of the standard STL).
Getting a specific value is simply writing:
twoDimensionalNodes[std::make_pair(x,y)]
(or use find if you're not sure if that value is in your map).
To iterate, just iterate over the unordered map:
for (auto it=twoDimensionalNodes.begin();it!=twoDimensionalNodes.end();++it)
{
std::cout << "x=" << it->first.first;
std::cout << "y=" << it->first.second;
std::cout << "value=" << it->second;
}
To make it a bit more readable, I prefer getting the coordinates first from the iterator, like this:
for (auto it=twoDimensionalNodes.begin();it!=twoDimensionalNodes.end();++it)
{
Coordinates &coordinates = it->first;
std::cout << "x=" << coordinates.first;
std::cout << "y=" << coordinates.second;
std::cout << "value=" << it->second;
}
If you have more than 2 dimensions, use std::tuple, or simply write your own Coordinates class to be used as key for the map.
Use std::unordered_map from <unordered_map>.
Try to specialize std hash class this way:
namespace std
{
template<typename T>
struct hash<void*>
{
std::size_t operator()(void * ptr) const
{
return (std::size_t)ptr;
}
};
}