Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > looping through hashmap

Reply
Thread Tools

looping through hashmap

 
 
Christian Gollwitzer
Guest
Posts: n/a
 
      11-02-2003
Hi,

I'm trying to loop over the elements in a hashmap of the
STL-implementation by SGI. The point is, that because the key/value pair
is stored as std:air in the COntainer, the code becomes very ugly
and unreadable soon. I'm aware that there exists the for_each-template,
but this doesn't make the code any better because the body of the
for-loop must then live in an extra function (consider two nested
loops). Now I tried to mimic the "for (key in array)"-construct of AWK
using the C++-preprocessor. I've come up with two different versions:

This one requires GNU-extensions (it's used to declare the Iterator in
the initializer-statement of the for loop, and simultaneously setting up
the loop-variables), but has the advantage that in use it looks like an
ordinary for-loop (refer to the sample program below)

#define FOREACH(key, value, hashmap) \
if (!hashmap.empty()) \
for ( { typedef typeof(hashmap) __type##hashmap; \
__type##hashmap::iterator __it##key=hashmap.begin(); \
value=__it##key->second; key=__it##key->first; } \
__it##key!=hashmap.end(); \
(++__it##key!=hashmap.end()) && \
(value=__it##key->second, &(key=__it##key->first)!=NULL) )


This one is (should be) ANSI-C++ compliant, but requires that you
structure the program using FOR..ENDFOR instead of curly braces (since I
need to set the variables inside the body of the for loop). It uses
references for the loop-variables that are automagically declared.

#define FORREF(key, value, hashmap) \
{ typedef typeof(hashmap) __type##hashmap; \
for (__type##hashmap::iterator __it##key=hashmap.begin(); \
__it##key!=hashmap.end(); \
++__it##key!=hashmap.end() ) { \
const __type##hashmap::key_type& key=__it##key->first; \
__type##hashmap::data_type& value=__it##key->second;

#define ENDFOR } }



Are there any pitfalls? I've used the ## tokenpaste operator to create
new variable names in order to avoid that there are identical ones for
nested loops.

Here is the sample application (count identical lines until eof is read)

#include <iostream>
#include <string>
#include <hash_map>
using namespace std;

class zeroint {
// int that initializes as 0
//
int value;
public:
zeroint(int v=0) : value(v) {}
zeroint(const zeroint& z) { value=z.value; }
zeroint& operator = (const zeroint& z) { value=z.value; return
*this; }
zeroint& operator ++ () { ++value; return *this; }
operator const int() const { return value; }
};


struct hash<string>:hash<const char*> {
size_t operator () (const string& x) const {
return this->hash<const char*>:perator () (x.c_str());
}
};

typedef hash_map<string, zeroint, hash<string> > stringmap;


int main() {
string mist;
stringmap wordmap;

//read in the lines
while (mist!="eof") {
cin>>mist;
++wordmap[mist];
}

//output the count using the first version
string word;
zeroint anzahl;
FOREACH(word, anzahl, wordmap) {
cout<<word<<"\t"<<anzahl<<endl;
}

cout<<endl;

// Application of the second version
// increase every mapped number by 10
FORREF(myword, numr, wordmap)
numr=numr+10;
ENDFOR

// output the count using the second version
// static_cast is necessary, because
// there is no operator<< for zeroints
FORREF(wortr, numr, wordmap)
cout<<wortr<<"\t"<<static_cast<const int&>(numr)<<endl;
ENDFOR

return 0;
}


--
Vale !
Christianus Auriocus

 
Reply With Quote
 
 
 
 
David Rubin
Guest
Posts: n/a
 
      11-03-2003
Christian Gollwitzer wrote:
> Hi,
>
> I'm trying to loop over the elements in a hashmap of the
> STL-implementation by SGI. The point is, that because the key/value pair
> is stored as std:air in the COntainer, the code becomes very ugly
> and unreadable soon. I'm aware that there exists the for_each-template,
> but this doesn't make the code any better because the body of the
> for-loop must then live in an extra function (consider two nested
> loops). Now I tried to mimic the "for (key in array)"-construct of AWK
> using the C++-preprocessor. I've come up with two different versions:


This is not such a big deal. For example, here is how I recently did it:

(Pardon the formatting. Map is basically a hash_map of words to list of
occurances by line number.)

typedef hash_map<string,
deque<int>,
hash<string>,
equal_to<string> > Map;

Map wmap;
/*...*/

/* display word and associated line numbers */
for(Map::iterator i=wmap.begin(); i != wmap.end(); ++i){
cout << (*i).first << " ";
copy((*i).second.begin(),
(*i).second.end(),
ostream_iterator<int>(cout, " "));
cout << endl;
}

The tricky part (and perhaps the ugly part) is getting the iterators to
the mapped value (as opposed to the key). You can wrap this in a macro,
function, or whatever you like.

/david

--
"As a scientist, Throckmorton knew that if he were ever to break wind in
the echo chamber, he would never hear the end of it."

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
looping in array vs looping in a dic giuseppe.amatulli@gmail.com Python 5 09-20-2012 11:58 PM
looping through json array loops through the characters instead ofthe values Aaron Javascript 2 04-10-2011 05:58 PM
reuse HashMap$Entry (or HashMap in total) to avoid millions of allocations Vince Darley Java 4 03-02-2010 07:48 AM
java.util.Properties extending from HashMap<Object, Object> insteadof HashMap<String, String> Rakesh Java 10 04-08-2008 04:22 AM
Looping through all the form fields in the code behind ? Aemca ASP .Net 1 07-22-2003 08:31 AM



Advertisments