Access to map data - c++

I have a complex map that defined
typedef short short1
typedef short short2
typedef map<short1,short2> data_list;
typedef map<string,data_list> table_list;
I have a class that fill table_list
class GroupingClass
{
table_list m_table_list;
string Buildkey(OD e1){
string ostring;
ostring+=string(e1.m_Date,sizeof(Date));
ostring+=string(e1.m_CT,sizeof(CT));
ostring+=string(e1.m_PT,sizeof(PT));
return ostring;
}
void operator() (const map<short1,short2>::value_type& myPair) {
OD e1=myPair.second;
string key=Buildkey(e1);
m_table_list[key][e1.m_short1]=e1.m_short2;
}
operator table_list() {
return m_table_list;
}
};
and I use it by
table_list TL2
GroupingClass gc;
TL2=for_each(mapOD.begin(), mapOD.end(), gc);
but when I try to access to internal map I have problems
for example
data_list tmp;
tmp=TL2["AAAA"];
short i=tmp[1]; //I dont update i variable
and when debug it, I see code try add new value to map.then when tmp var is const this cause to a error
but if i use a loop by itrator this work properly
why this no work at first way
thanks herzl

std::map<Key,Value>::operator[](Key const& k) will look for key k. If it's not found, it will insert a new Value() and return a reference to that. This is a modifying operation. Therefore, operator[] is non-const.

The code does not make sense. What is OD? myPair.second would be short in operator() but then you do e1.m_short2 which does not make any sense.
Your likely bug is that for_each takes its 3rd parameter by value which means it is going to make copies of that map and probably you will lose the changes.
You can force for_each to take the 3rd value by reference either by specifying the template parameter directly or by wrapping in boost::ref. However you would do far better to make your functor take the map it is building by reference in its constructor rather than have an instance of a map.
class GroupingClass
{
table_list & m_table_list;
string Buildkey(OD e1)
{
string ostring;
ostring+=string(e1.m_Date,sizeof(Date));
ostring+=string(e1.m_CT,sizeof(CT));
ostring+=string(e1.m_PT,sizeof(PT));
return ostring;
}
public:
explicit GroupingClass( table_list & the_table_list ) :
m_table_list( the_table_list )
{
}
void operator() (const map<short1,short2>::value_type& myPair) const
{
OD e1(myPair.first); // probably what you meant
string key=Buildkey(e1);
m_table_list[key][e1.m_short1]=e1.m_short2;
// did you mean m_table_list[key][myPair.first] = myPair.second; ?
}
};
and use it by
table_list TL2;
for_each(mapOD.begin(), mapOD.end(), GroupingClass(TL2));

Related

c++ extract member of a key of a std::multiset into a std::vector without having a getter

I encountered the problem during an interview. I had to create a multimap which had as keys objects with one private member(a string, the name of the object) and mapped value ints(not relevant). There was one restriction imposed by the person leading the interview: there should be not get or set functions associated to the member string of the object. After some processing of the multimap with STL functions(like removing some elements), the following was requested: to extract the name of the key objects into a vector while removing any duplicates. I do not know how to extract the name of the key objects without having a get function(I could remove the duplicates once the extraction is performed). The person leading the interview brought into discussion functors and possibility to use a functor which could be a friend of the Object class.
Please let me know if you have any idea how this could be solved!
I provide bellow a simplified version of the code creating the multimap.
class Object
{
std::string m_name; /* no set or get function allowed */
public:
Object(std::string name): m_name(name) {}
friend bool operator< (const Object& o1, const Object& o2)
{
return o1.m_name.compare(o2.m_name) < 0;
}
};
void testMap()
{
std::multimap<Object, int> m1;
m1.insert(std::make_pair(Object("abc"), 1));
m1.insert(std::make_pair(Object("qwerty"), 2));
m1.insert(std::make_pair(Object("def"), 3));
m1.insert(std::make_pair(Object("qwerty"), 4))
/* extract Objects names in a vector while removing duplicates without adding a get m_name function */
}
Please let me know if you have any idea how this could be solved! I do not know how to access m_name which is private without a get function...
Not a nice solution, but using the fact that m1.begin() will always point to the alphabeticly first element we can decide if a given string would be the first in it, by inserting it to the map, and erasing it after the check. So we can start a binary-search caracter by character for the first string. Using this we can extract all keys from the map (by removing the already ones we find). I know this solution is a bit unortodox, and making a getter (or a friend function/class what is effectively a getter) is way better, but this can be done without modifying the class.
bool is_first(std::string s,std::multimap<Object,int>& m){
auto it=m.insert(std::make_pair(Object(s), -1));
bool res=it==m.begin();
m.erase(it);
return res;
}
bool eq(const Object&a,const Object& b){
return (!(a<b)) && (!(b<a));
}
std::string get_first(std::multimap<Object,int> m){
int len=0;
std::string res;
while (1){
char mn=-128,mx=127,mid;
res+=mn;
while(mn+1!=mx){
mid=(mn+(int)mx)/2;
res[len]=mid;
if (is_first(res,m)){
mn=mid;
}else{
mx=mid;
if (eq(m.begin()->first,Object(res)))
return res;
}
}
res[len]=mn;
++len;
}
}
void testMap()
{
std::multimap<Object, int> m1;
m1.insert(std::make_pair(Object("abc"), 1));
m1.insert(std::make_pair(Object("abc"), 1));
m1.insert(std::make_pair(Object("qwerty"), 2));
m1.insert(std::make_pair(Object("def"), 3));
m1.insert(std::make_pair(Object("qwerty"), 4));
while (!m1.empty()){
std::string s=get_first(m1);
std::cout<<s<<" ";
m1.erase(s);
}
}
The motto for this solution: "If it stupid but it works, then it isn't stupid"
If the interviewer mentioned "to use a functor which could be a friend of the Object class," this implies that you are allowed to modify class Object by adding a friend declaration. In that case, you can simply add a friend function (I don't see why a Functor would be better) like
class Object
{
std::string m_name; /* no set or get function allowed */
public:
Object(std::string name): m_name(name) {}
friend bool operator< (const Object& o1, const Object& o2)
{
return o1.m_name.compare(o2.m_name) < 0;
}
friend std::string name(const Object& o)
{
return o.m_name;
}
};
I cannot be sure, though, that the interviewer had this in mind; as #NathanOliver mentioned, there is a template trick to access a private member, but I cannot imagine that someone would ask that at an interview.

Overloaded [] operator for hash table to a vector

I am working on a simple hash table in C++. I have methods to insert, delete, and search the hash table for the specified key. I know that the C++ map STL container can handle my situation, but I would kind of like to code my own as an educational exercise.
Basically I have a hash table that will take a single string and map it to a vector of other strings. This is easy to do in a method because calling a .Add() or .Delete() will behave as expected. I would however like to create an overloaded [] operator to the class that is able to do these operations on the vector.
For example, if I want to add an item to the vector I can write something like this:
hashTable[string1] = newString;
This will set the new string as a member of my vector. The same can be said for delete and search.
hashTable[string1] = "";
cout << hashTable[string1] << endl;
My major problem is that I do not know how to overload the [] operator to gain this functionality. I have this function coded up right now. It works on a basic 1 to 1 string match, but not on a string to vector match.
//Return a reference to a vector to update then reassign?
vector& HashClass::operator[](const string index)
{
assert(size >= 0 && size < maxSize);
Hash(key);
return hashTable[index];
}
I think I'm most stuck on the idea of having a vector return that later needs to be assigned. As the user, I would find this kludgy.
This question is closely related to another question: what behavior do
you want when you access a non-existant value other than in an
assignment? In other words, what do you want to happen when you write:
std::cout << hashTable[string] << std::endl;
and string is not present in the table?
There are two possible approaches: you can consider it an error, and
throw an exception, or abort, or something similar; or you can return
some sort of default, built with the default constructor, or provided by
the client earlier.
The standard map and unordered_map take the second approach, using the
default constructor to construct a new value. This allows a very simple
solution: if operator[] isn't present, you insert it, initializing it
with the default value. Then you return a reference to it;
hashTable[string] = newString; assigns through the reference to an
already existing value.
In many use cases, the first approach will be preferable (perhaps with a
contains function, so you can test up front whether the operator[]
will find something or not). To implement the first approach, you must
first implement specific functions for each type of access:
template <typename Key, typename Value>
class HashTable
{
public:
Value* get( Key const& key ) const;
void set( Key const& key, Value const& value );
};
(I generally make these public; there's no reason to forbid their use by
a client.)
Then, you define operator[] to return a proxy, as follows:
template <typename Key, typename Value>
class HashTable
{
public:
class Proxy
{
HashTable* myOwner;
Key myKey;
public:
Proxy( HashTable* owner, Key const& key )
: myOwner( owner )
, myKey( key )
{
}
operator Value const&() const
{
Value const* result = myOwner->get( myKey );
if ( result == NULL ) {
// Desired error behavior here...
}
return *result;
}
Proxy const& operator==( Value const& value ) const
{
myOwner->set( myKey, value );
return *this;
}
};
Value* get( Key const& key ) const;
void set( Key const& key, Value const& value );
Proxy operator[]( Key const& key )
{
return Proxy( this, key );
}
};
Thus, when you write:
hashTable[key] = newString;
, the proxy's operator= will call hashTable.put( key, newString );
in other contexts, however, it will call the implicit type conversion on
the proxy, which calls hashTable.get( key ).
In some cases, even if you desire to return a default value, it may be
preferable to use this solution: the get function is not required to
insert anything into the hash table, so the table doesn't fill up with
all of the misses, and you can overload the operator[] on const, so
you can use it on a const hash table as well. Also, it doesn't
require the value type to have a default constructor.
It does have one disadvantage with respect to the solution used in the
standard; since you can't overload operator., you can't make the proxy
behave like a reference, and things like:
hashTable[string].someFunction();
don't work. A work-around is to overload operator-> in the proxy, but
this leads to a somewhat unnatural syntax:
hashTable[string]->someFunction(); // But the hash table contains
// values, not pointers!!!
(Don't be mislead by the implicit conversion to a reference. An
implicit conversion will not be considered for a in an expression
a.b.)
In C++, [] access to associative containers is generally given the semantics of default-constructing an object of the mapped type, inserting it with the key, and returning a reference to the inserted mapped object.
So your operator[] would be implemented as:
string& HashClass::operator[](const string index)
{
assert(size >= 0 && size < maxSize);
Hash(key);
vector &v = hashTable[index];
if (index in v) {
...
} else {
v.push_back(string());
return v.back();
}
}

How to create map with keys/values inside class body once (not each time functions from class are called)

I would like to create C++ class which would allow to return value by given key from map, and key by given value. I would like also to keep my predefined map in class content. Methods for getting value or key would be static. How to predefine map statically to prevent creating map each time I call getValue(str) function?
class Mapping
{
static map<string, string> x;
Mapping::Mapping()
{
x["a"] = "one";
x["b"] = "two";
x["c"] = "three";
}
string getValue(string key)
{
return x[key];
}
string getKey(string value)
{
map<string, string>::const_iterator it;
for (it = x.begin(); it < x.end(); ++it)
if (it->second == value)
return it->first;
return "";
}
};
string other_func(string str)
{
return Mapping.getValue(str); // I don't want to do: new Mapping().getValue(str);
}
Function other_func is called often so I would prefer to use map which is created only once (not each time when other_func is called). Do I have to create instance of Mapping in main() and then use it in other_func (return instance.getValue(str)) or is it possible to define map in class body and use it by static functions?
Is this what you want?
#include <map>
#include <string>
class Mapping
{
private:
// Internally we use a map.
// But typedef the class so it is easy to refer too.
// Also if you change the type you only need to do it in one place.
typedef std::map<std::string, std::string> MyMap;
MyMap x; // The data store.
// The only copy of the map
// I dont see any way of modifying so declare it const (unless you want to modify it)
static const Mapping myMap;
// Make the constructor private.
// This class is going to hold the only copy.
Mapping()
{
x["a"] = "one";
x["b"] = "two";
x["c"] = "three";
}
public:
// Public interface.
// Returns a const reference to the value.
// The interface use static methods (means we dont need an instance)
// Internally we refer to the only instance.
static std::string const& getValue(std::string const& value)
{
// Use find rather than operator[].
// This way you dont go inserting garbage into your data store.
// Also it allows the data store to be const (as operator may modify the data store
// if the value is not found).
MyMap::const_iterator find = myMap.x.find(value);
if (find != myMap.x.end())
{
// If we find it return the value.
return find->second;
}
// What happens when we don;t find anything.
// Your original code created a garbage entry and returned that.
// Could throw an exception or return a temporary reference.
// Maybe -> throw int(1);
return "";
}
};
First of all, you might want to look up Boost::MultiIndex and/or Boost::bimap. Either will probably help a bit with your situation of wanting to use either one of the paired items to look up the other (bimap is more directly what you want, but if you might need to add a third, fourth, etc. key, then MultiIndex may work better). Alternatively, you might want to just use a pair of sorted vectors. For situations like this where the data remains constant after it's been filled in, these will typically allow faster searching and consume less memory.
From there, (even though you don't have to make it explicit) you can handle initialization of the map object itself a bit like a singleton -- put the data in the first time it's needed, and from then on just use it:
class Mapping {
static map<string, string> x;
static bool inited;
public:
Mapping() {
if (!inited) {
x["a"] = "one";
x["b"] = "two";
x["c"] = "three";
inited = true;
}
}
string getValue(string const &key) { return x[key]; }
};
// This initialization is redundant, but being explicit doesn't hurt.
bool Mapping::inited = false;
map<string, string> Mapping::x;
With this your some_func could look something like this:
string some_func(string const &input) {
return Mapping().getValue(input);
}
This still has a little overhead compared to pre-creating and using an object, but it should be a lot less than re-creating and re-initializing the map (or whatever) every time.
If you are looking up the value from the key a lot, you will find it easier and more efficient to maintain a second map in parallel with the first.
You don't need to create a static map especially if you ever want to create multiple Mapping objects. You can create the object in main() where you need it, and pass it around by reference, as in:
string other_func(Mapping &mymap, string str)
{
return mymap.getValue(str);
}
Of course this raises questions about efficiency, with lots of strings being copied, so you might want to just call getValue directly without the extra overhead of calling other_func.
Also, if you know anything about the Boost libraries, then you might want to read up on Boost.Bimap which is sort of what you are implementing here.
http://www.boost.org/doc/libs/1_42_0/libs/bimap/doc/html/index.html
Static is bad. Don't. Also, throw or return NULL pointer on not found, not return empty string. Other_func should be a member method on the object of Mapping, not a static method. This whole thing desperately needs to be an object.
template<typename Key, typename Value> class Mapping {
std::map<Key, Value> primmap;
std::map<Value, Key> secmap;
public:
template<typename Functor> Mapping(Functor f) {
f(primmap);
struct helper {
std::map<Value, Key>* secmapptr;
void operator()(std::pair<Key, Value>& ref) {
(*secmapptr)[ref.second] = ref.first;
}
};
helper helpme;
helpme.secmapptr = &secmap;
std::for_each(primmap.begin(), primmap.end(), helpme);
}
Key& GetKeyFromValue(const Value& v) {
std::map<Value,Key>::iterator key = secmap.find(v);
if (key == secmap.end())
throw std::runtime_error("Value not found!");
return key->second;
}
Value& GetValueFromKey(const Key& k) {
std::map<Key, Value>::iterator key = primmap.find(v);
if (key == primmap.end())
throw std::runtime_error("Key not found!");
return key->second;
}
// Add const appropriately.
};
This code uses a function object to initialize the map, reverses it for you, then provides accessing methods for the contents. As for why you would use such a thing as opposed to a raw pair of std::maps, I don't know.
Looking at some of the code you've written, I'm guessing that you originate from Java. Java has a lot of things that C++ users don't use (unless they don't know the language) like singletons, statics, and such.

Find array element by member value - what are "for" loop/std::map/Compare/for_each alternatives?

Example routine:
const Armature* SceneFile::findArmature(const Str& name){
for (int i = 0; i < (int)armatures.size(); i++)
if (name == armatures[i].name)
return &armatures[i];
return 0;
}
Routine's purpose is (obviously) to find a value within an array of elements, based on element's member variable, where comparing member variable with external "key" is search criteria.
One way to do it is to iterate through array in loop. Another is to use some kind of "map" class (std::map, some kind of vector sorted values + binarySearch, etc, etc). It is also possible to make a class for std::find or for std::for_each and use it to "wrap" the iteration loop.
What are other ways to do that?
I'm looking for alternative ways/techniques to extract the required element.
Ideally - I'm looking for a language construct, or a template "combo", or a programming pattern I don't know of that would collapse entire loop or entire function into one statement. Preferably using standard C++/STL features (no C++0x, until it becomes a new standard) AND without having to write additional helper classes (i.e. if helper classes exist, they should be generated from existing templates).
I.e. something like std::find where comparison is based on class member variable, and a variable is extracted using standard template function, or if variable (the one compared against "key"("name")) in example can be selected as parameter.
The purpose of the question is to discover/find language feature/programming technique I don't know yet. I suspect that there may be an applicable construct/tempalte/function/technique similar to for_each, and knowing this technique may be useful. Which is the main reason for asking.
Ideas?
If you have access to Boost or another tr1 implementation, you can use bind to do this:
const Armature * SceneFile::findArmature(const char * name) {
find_if(armatures.begin(), armatures.end(),
bind(_stricmp, name, bind(&string::c_str, bind(&Armature::name, _1))) == 0);
}
Caveat: I suspect many would admit that this is shorter, but claim it fails on the more elegant/simpler criteria.
Sure looks like a case for std::find_if -- as the predicate, you could use e.g. a suitable bind1st. I'm reluctant to say more as this smacks of homework a lot...;-).
Why 5 lines? Clean doesn't have a number attached to it. In fact, clean code might take more lines in the utility classes, which can then be reused over and over. Don't restrict yourself unnecessarily.
class by_name
{
public:
by_name(const std::string& pName) :
mName(pName)
{}
template <typename T>
bool operator()(const T& pX)
{
return pX.name == pName;
}
private:
std::string mName;
};
Then:
const Armature* SceneFile::findArmature(const char* name)
{
// whatever the iterator type name is
auto iter = std::find_if(armatures.begin(), armatures.end(), by_name(name));
return iter == armatures.end() ? 0 : &(*iter);
}
Within restriction:
class by_name { public: by_name(const std::string& pName) : mName(pName) {} template <typename T> bool operator()(const T& pX) { return pX.name == pName; } private: std::string mName; };
Then:
const Armature* SceneFile::findArmature(const char* name)
{
// whatever the iterator type name is
auto iter = std::find_if(armatures.begin(), armatures.end(), by_name(name));
return iter == armatures.end() ? 0 : &(*iter);
}
:)
C++0x has ranged-based for-loops, which I think would make the most elegant solution:
const Armature* SceneFile::findArmature(const std::string& pName) const
{
for (auto a : armatures)
{
if (a.name = pName) return &a;
}
return 0;
}
You would probably need to use STL map. It gives you possibility to get the element using keys. Your key would be the name of armature.
http://www.cplusplus.com/reference/stl/map/
EDIT: :D
one liner B-)
const Armature* SceneFile::findArmature(const Str& name){for (int i = 0; i < (int)armatures.size(); i++) if(name == armatures[i].name) return &armatures[i]; return 0;}
Holy shiz, you're using _stricmp? FAIL. Also, you didn't actually tell us the type of the vectors or any of the variables involved, so this is just guesswork.
const Armature* SceneFile::findArmature(const std::string& lols) {
for(auto it = armatures.begin(); it != armatures.end(); it++) {
if (boost::iequals(lols, (*it).name))
return &(*it);
return NULL;
}
Ultimately, if you need this, you should put the armatures or pointers to them in a std::map. A vector is the wrong container if you're searching into it, they're best for when the collection is what's important rather than any finding behaviour.
Edited to use a std::string reference.

How to iterate over a std::map full of strings in C++

I have the following issue related to iterating over an associative array of strings defined using std::map.
-- snip --
class something
{
//...
private:
std::map<std::string, std::string> table;
//...
}
In the constructor I populate table with pairs of string keys associated to string data. Somewhere else I have a method toString that returns a string object that contains all the keys and associated data contained in the table object(as key=data format).
std::string something::toString()
{
std::map<std::string, std::string>::iterator iter;
std::string* strToReturn = new std::string("");
for (iter = table.begin(); iter != table.end(); iter++) {
strToReturn->append(iter->first());
strToReturn->append('=');
strToRetunr->append(iter->second());
//....
}
//...
}
When I'm trying to compile I get the following error:
error: "error: no match for call to ‘(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >) ()’".
Could somebody explain to me what is missing, what I'm doing wrong?
I only found some discussion about a similar issue in the case of hash_map where the user has to define a hashing function to be able to use hash_map with std::string objects. Could be something similar also in my case?
Your main problem is that you are calling a method called first() in the iterator. What you are meant to do is use the property called first:
...append(iter->first) rather than ...append(iter->first())
As a matter of style, you shouldn't be using new to create that string.
std::string something::toString()
{
std::map<std::string, std::string>::iterator iter;
std::string strToReturn; //This is no longer on the heap
for (iter = table.begin(); iter != table.end(); ++iter) {
strToReturn.append(iter->first); //Not a method call
strToReturn.append("=");
strToReturn.append(iter->second);
//....
// Make sure you don't modify table here or the iterators will not work as you expect
}
//...
return strToReturn;
}
edit: facildelembrar pointed out (in the comments) that in modern C++ you can now rewrite the loop
for (auto& item: table) {
...
}
Don't write a toString() method. This is not Java. Implement the stream operator for your class.
Prefer using the standard algorithms over writing your own loop. In this situation, std::for_each() provides a nice interface to what you want to do.
If you must use a loop, but don't intend to change the data, prefer const_iterator over iterator. That way, if you accidently try and change the values, the compiler will warn you.
Then:
std::ostream& operator<<(std::ostream& str,something const& data)
{
data.print(str)
return str;
}
void something::print(std::ostream& str) const
{
std::for_each(table.begin(),table.end(),PrintData(str));
}
Then when you want to print it, just stream the object:
int main()
{
something bob;
std::cout << bob;
}
If you actually need a string representation of the object, you can then use lexical_cast.
int main()
{
something bob;
std::string rope = boost::lexical_cast<std::string>(bob);
}
The details that need to be filled in.
class somthing
{
typedef std::map<std::string,std::string> DataMap;
struct PrintData
{
PrintData(std::ostream& str): m_str(str) {}
void operator()(DataMap::value_type const& data) const
{
m_str << data.first << "=" << data.second << "\n";
}
private: std::ostream& m_str;
};
DataMap table;
public:
void something::print(std::ostream& str);
};
Change your append calls to say
...append(iter->first)
and
... append(iter->second)
Additionally, the line
std::string* strToReturn = new std::string("");
allocates a string on the heap. If you intend to actually return a pointer to this dynamically allocated string, the return should be changed to std::string*.
Alternatively, if you don't want to worry about managing that object on the heap, change the local declaration to
std::string strToReturn("");
and change the 'append' calls to use reference syntax...
strToReturn.append(...)
instead of
strToReturn->append(...)
Be aware that this will construct the string on the stack, then copy it into the return variable. This has performance implications.
Note that the result of dereferencing an std::map::iterator is an std::pair. The values of first and second are not functions, they are variables.
Change:
iter->first()
to
iter->first
Ditto with iter->second.
iter->first and iter->second are variables, you are attempting to call them as methods.
Use:
std::map<std::string, std::string>::const_iterator
instead:
std::map<std::string, std::string>::iterator
Another worthy optimization is the c_str ( ) member of the STL string classes, which returns an immutable null terminated string that can be passed around as a LPCTSTR, e. g., to a custom function that expects a LPCTSTR. Although I haven't traced through the destructor to confirm it, I suspect that the string class looks after the memory in which it creates the copy.
In c++11 you can use:
for ( auto iter : table ) {
key=iter->first;
value=iter->second;
}