Extracting keys and values in a map.

R

Ram

Hi,

I would like a sequence view of keys and values in a map, i.e. to
extract keys/values instead of using a loop

std::map<T1, T2> m;
std::list<T2> l;
// ...
std::map<T1, T2>::iterator it;
for(it = m.begin(); it != m.end(); ++it)
l.push_back(it->second);

I want to say something like

std::map<T1, T2> m;
std::list<T2> l;
// ...
std::copy(m.value_begin(), m.value_end(), std::inserter(l, l.end()));

In short my question reduces to- is there a simple way to get an
appropriate type of iterator from a map which on de-referencing gives
me key/value of the map.

I know its not difficult to roll out my own, just wondering whether
there's already a way to do it.

Thanks
Ram
 
V

Victor Bazarov

Ram said:
[..]
In short my question reduces to- is there a simple way to get an
appropriate type of iterator from a map which on de-referencing gives
me key/value of the map.

WTF is "key/value"? Dereferencing a map iterator gives you a pair
(which is what 'value_type' of the map is). You can always write your
adapter to get the "second" member of it (or the "first").
I know its not difficult to roll out my own, just wondering whether
there's already a way to do it.

To do what? Extract "second"? Boost has an adapter for it, IIRC,
but if you're not currently using Boost, rolling your own is simpler
than waiting for it to tricle into the library implemenations.

<rant>
Programming always involves writing a bunch of small utility code that
serves some special needs. Why everybody keeps asking if all those
special needs have already been addressed in the library is beyond me,
aren't there books from which you can learn what is and what isn't in
the standard library? Do your homework before coming here. Try not
to use this newsgroup like a live reference manual for C++...
</rant>

V
 
R

Ram

Victor said:
Ram said:
[..]
In short my question reduces to- is there a simple way to get an
appropriate type of iterator from a map which on de-referencing gives
me key/value of the map.

WTF is "key/value"? Dereferencing a map iterator gives you a pair
(which is what 'value_type' of the map is). You can always write your
adapter to get the "second" member of it (or the "first").

I know I could always write my own adapter (and how). Thats not the
point here.
To do what? Extract "second"? Boost has an adapter for it, IIRC,
but if you're not currently using Boost, rolling your own is simpler
than waiting for it to tricle into the library implemenations.

<rant>
Programming always involves writing a bunch of small utility code that
serves some special needs. Why everybody keeps asking if all those
special needs have already been addressed in the library is beyond me,
aren't there books from which you can learn what is and what isn't in
the standard library? Do your homework before coming here. Try not
to use this newsgroup like a live reference manual for C++...
</rant>

I find your rant unjustified. IMO this is not a very special need.
While using std::map many times I have found the need to extract just
keys (or values) in the map. And most of the time I have rolled my own
loops.

I ain't trying to use this newsgroup as a live reference manual. Have a
couple of them and its easier to use them than posting here. I found a
way using boost::lambda and boost::bind but the syntax didn't satisfy
me. My purpose of posting this here was to get some idea of how to do
it in a concise and elegant manner. If this newsgroup is not for this I
wonder what it is for.

Ram
 
V

Victor Bazarov

Ram said:
Victor said:
Ram said:
[..]
I know its not difficult to roll out my own, just wondering whether
there's already a way to do it.

To do what? Extract "second"? Boost has an adapter for it, IIRC,
but if you're not currently using Boost, rolling your own is simpler
than waiting for it to tricle into the library implemenations.

<rant>
Programming always involves writing a bunch of small utility code
that serves some special needs. Why everybody keeps asking if all
those special needs have already been addressed in the library is
beyond me, aren't there books from which you can learn what is and
what isn't in the standard library? Do your homework before coming
here. Try not to use this newsgroup like a live reference manual
for C++... </rant>

I find your rant unjustified. [...]

I am sorry. Unjustified?! You asked (see above) whether there's already
a way to do it. "Already". What does that mean to you? "There": where?
We can only tell you about the language and about the library. That's
the only "there" where anything can be, AFA c.l.c++ is concerned.

I suggested (against my better judgement, apparently) to look at Boost.
But if you find Boost syntax unsatisfactory, well, how can we help?

If you know how to roll your own, isn't that "a way to do it" that is
"already" "there"? How much more elegant do you need to get beyond
a simple 'for' loop? I told you about the adapter that you can write.
Do you expect me to write it for you, or are you a programmer yourself?

OK, here you go:
-------------------
#include <map>
#include <iterator>

template<class mi, class t> struct key_iterator_tag
{
typedef std::input_iterator_tag iterator_category;
typedef t value_type;
typedef ptrdiff_t difference_type;
typedef difference_type distance_type; // retained
typedef t* pointer;
typedef t& reference;

mi iter;
key_iterator_tag(mi it) : iter(it) {}

bool operator !=(key_iterator_tag const& other) const {
return iter != other.iter;
}

bool operator ==(key_iterator_tag const& other) const {
return iter == other.iter;
}

key_iterator_tag& operator++() { ++iter; return *this; }
key_iterator_tag operator++(int) {
key_iterator_tag i(*this); ++iter; return i; }
t operator*() const { return (*iter).first; }
};

template<class mi, class t> struct mapped_iterator_tag
{
typedef std::input_iterator_tag iterator_category;
typedef t value_type;
typedef ptrdiff_t difference_type;
typedef difference_type distance_type; // retained
typedef t* pointer;
typedef t& reference;

mi iter;
mapped_iterator_tag(mi it) : iter(it) {}

bool operator !=(mapped_iterator_tag const& other) const {
return iter != other.iter;
}

bool operator ==(mapped_iterator_tag const& other) const {
return iter == other.iter;
}

mapped_iterator_tag& operator++() { ++iter; return *this; }
mapped_iterator_tag operator++(int) {
mapped_iterator_tag i(*this); ++iter; return i; }
t& operator*() { return (*iter).second; }
};

template<class mi>
key_iterator_tag<typename mi::iterator, typename mi::key_type>
key_begin(mi& m) {
return key_iterator_tag<typename mi::iterator, typename
mi::key_type>(m.begin());
}

template<class mi>
key_iterator_tag<typename mi::iterator, typename mi::key_type>
key_end(mi& m) {
return key_iterator_tag<typename mi::iterator, typename
mi::key_type>(m.end());
}

template<class mi>
mapped_iterator_tag<typename mi::iterator, typename mi::mapped_type>
mapped_begin(mi& m) {
return mapped_iterator_tag<typename mi::iterator, typename
mi::mapped_type>(m.begin());
}

template<class mi>
mapped_iterator_tag<typename mi::iterator, typename mi::mapped_type>
mapped_end(mi& m) {
return mapped_iterator_tag<typename mi::iterator, typename
mi::mapped_type>(m.end());
}

#include <iostream>
#include <list>
#include <algorithm>

int main(int argc, char** argv)
{
std::map<int,char> mic;
mic[1] = 'a';
mic[3] = 'b';
mic[2] = 'c';
std::list<int> li;
std::list<char> lc;
std::copy(key_begin(mic), key_end(mic), back_inserter(li));
for (std::list<int>::iterator i = li.begin(); i != li.end(); ++i)
std::cout << *i << std::endl;
std::copy(mapped_begin(mic), mapped_end(mic), back_inserter(lc));
for (std::list<char>::iterator i = lc.begin(); i != lc.end(); ++i)
std::cout << *i << std::endl;
}
-------------------

Now, the use of those is 'key_begin(somemap)' and 'key_end(somemap)' and
they are input iterators. Is that elegant enough? Probably not. You work
on improving the elegance, I'm done.

V
 
D

Dilip

Victor said:
Ram said:
Victor said:
Ram wrote:
[..]
I know its not difficult to roll out my own, just wondering whether
there's already a way to do it.

To do what? Extract "second"? Boost has an adapter for it, IIRC,
but if you're not currently using Boost, rolling your own is simpler
than waiting for it to tricle into the library implemenations.

<rant>
Programming always involves writing a bunch of small utility code
that serves some special needs. Why everybody keeps asking if all
those special needs have already been addressed in the library is
beyond me, aren't there books from which you can learn what is and
what isn't in the standard library? Do your homework before coming
here. Try not to use this newsgroup like a live reference manual
for C++... </rant>

I find your rant unjustified. [...]

I am sorry. Unjustified?! You asked (see above) whether there's already
a way to do it. "Already". What does that mean to you? "There": where?
We can only tell you about the language and about the library. That's
the only "there" where anything can be, AFA c.l.c++ is concerned.

I second Ram. In addition to being the patrolman for this NG you are
unnecessarily being heavy handed on posters who are genuinely trying to
find a *better* solution to a problem they face. Not everyone can
quote the standard like you do nor do they have the breadth of
expertise you do. Admittedly you have spent time & energy getting
there, but lesser mortals like us are not there yet.

You have wasted 2 lengthy posts on semantic clinton-esque mumbo-jumbo
(it depends on what you mean by "what") when it would have been far
more easier to either ignore that post altogether or else post a quick
snippet (as long as the topic is not OT). I am sure for someone like
you it'd be childs play. Whether you want to spend time doing that is
a separate issue -- I do not however think you have a right to question
the OP's motives.

I posted a similar question in another thread. Its not that I don't
want to do some thinking myself (In fact I have). Its just that my
knowledge and my capacity is limited to what I know. The motivation
behind my post sometimes is a reply can teach you a lot -- like the one
where you showed me how to use a << operator to wrap a legacy logging
library. It maybe simple for you but it opened some possibilities for
me.

You need to cut us some slack every now & then.
 
J

Jonathan Mcdougall

Victor said:
Ram said:
Victor said:
Ram wrote:
[..]
I know its not difficult to roll out my own, just wondering whether
there's already a way to do it.

To do what? Extract "second"? Boost has an adapter for it, IIRC,
but if you're not currently using Boost, rolling your own is simpler
than waiting for it to tricle into the library implemenations.

<rant>
Programming always involves writing a bunch of small utility code
that serves some special needs. Why everybody keeps asking if all
those special needs have already been addressed in the library is
beyond me, aren't there books from which you can learn what is and
what isn't in the standard library? Do your homework before coming
here. Try not to use this newsgroup like a live reference manual
for C++... </rant>

I find your rant unjustified. [...]

I am sorry. Unjustified?! You asked (see above) whether there's already
a way to do it. "Already". What does that mean to you? "There": where?
We can only tell you about the language and about the library. That's
the only "there" where anything can be, AFA c.l.c++ is concerned.

I suggested (against my better judgement, apparently) to look at Boost.
But if you find Boost syntax unsatisfactory, well, how can we help?

If you know how to roll your own, isn't that "a way to do it" that is
"already" "there"? How much more elegant do you need to get beyond
a simple 'for' loop? I told you about the adapter that you can write.
Do you expect me to write it for you, or are you a programmer yourself?

OK, here you go:

Now, the use of those is 'key_begin(somemap)' and 'key_end(somemap)' and
they are input iterators. Is that elegant enough? Probably not. You work
on improving the elegance, I'm done.

Victor,

This tone is unacceptable here. Although your contribution to
comp.lang.c++ is extremely valuable, please do make an effort to keep
conversations pleasant for everybody, readers and posters.


Jonathan
 
V

Victor Bazarov

Dilip said:
[..]
I second Ram.

On what grounds?
In addition to being the patrolman for this NG you are
unnecessarily being heavy handed on posters [..]

Patrolman? Heavy handed? Huh?
I posted a similar question in another thread. Its not that I don't
want to do some thinking myself (In fact I have). Its just that my
knowledge and my capacity is limited to what I know. The motivation
behind my post sometimes is a reply can teach you a lot -- like the
one where you showed me how to use a << operator to wrap a legacy
logging library. It maybe simple for you but it opened some
possibilities for me.

But it is all described in a few books I've managed to read during off
hours, or between coding, when the projects are being built. If you
(or Ram) don't want to spend time reading those same books or doing
research elsewhere, I'm gonna rant about it. And nothing you can do
'bout that. I ain't gonna change. Live with it.
You need to cut us some slack every now & then.

And do *I* get any slack at all? Pff... Forget it! Not worth my time.

V
 
V

Victor Bazarov

Jonathan said:
Victor,

This tone is unacceptable here. Although your contribution to
comp.lang.c++ is extremely valuable, please do make an effort to keep
conversations pleasant for everybody, readers and posters.

You know what, wrong time, buddy. I am not going to be insulted in
this way.
 
D

Dilip

Victor said:
Dilip said:
[..]
In addition to being the patrolman for this NG you are
unnecessarily being heavy handed on posters [..]

Patrolman? Heavy handed? Huh?

This snip is a shining example:

"I'm gonna rant about it. And nothing you can do
'bout that. I ain't gonna change. Live with it."

If that is not heavy handed I don't know what is.
If you
(or Ram) don't want to spend time reading those same books or doing
research elsewhere,

That is where you start the assumption phase. Maybe we did the
research, maybe we read the same books, maybe we just didn't know where
to look or maybe we looked and we still didn't get it. Maybe we kept
running into deadlines thats not allowing us enough time to investigate
all possibilities. Thats what I meant by "capacity". Some people get
that epiphany faster than others. Humility means sharing what you know
and not reflexively questioning every one's motivation. No one is
downplaying your contribution to this NG -- we only ask you to simmer
down a little bit.
And do *I* get any slack at all? Pff... Forget it! Not worth my time.

Thats exactly what I mean. When something is not worth your time, just
ignore it. What does ranting publicly buy you other than maybe making
you feel good for that few minutes?
 
J

Jonathan Mcdougall

Victor said:
You know what, wrong time, buddy. I am not going to be insulted in
this way.

I don't know you, why would I insult you? I am sorry to see you taking
things this way. Anyways, this thread is closed for me.


Jonathan
 
R

Ram

[...]
I find your rant unjustified. [...]

I am sorry. Unjustified?! You asked (see above) whether there's already
a way to do it. "Already". What does that mean to you? "There": where?
We can only tell you about the language and about the library. That's
the only "there" where anything can be, AFA c.l.c++ is concerned.

I think it was clear that I was not asking for a pointer to the
standard library. You could have pointed me to the boost adapter you
talked about and that would have done. IMO language is not only about
the syntax and the library but also about the way it facilitates one to
solve a problem.
I suggested (against my better judgement, apparently) to look at Boost.
But if you find Boost syntax unsatisfactory, well, how can we help?

By suggesting some simple way to provide my own.
If you know how to roll your own, isn't that "a way to do it" that is
"already" "there"? How much more elegant do you need to get beyond
a simple 'for' loop? I told you about the adapter that you can write.
Do you expect me to write it for you, or are you a programmer yourself?

OK, here you go:

I didn't expect you to write it for me, rather to provide some ideas in
that direction. For example, one suggestion would be to derive from
std::map<T1, T2>::iterator that overrides operators * and -> to return
appropriate type as I have done below for keys-

template <class T1, class T2>
struct key_iterator: public std::map<T1, T2>::iterator
{
typedef typename std::map<T1, T2>::iterator base_t;
typedef const T1* pointer; // override
typedef const T1& reference; // override

reference operator*() const
{ return base_t::eek:perator*().first; }

pointer operator->() const
{ return &(base_t::eek:perator*().first); }

key_iterator() {}
key_iterator(base_t b): base_t(b) {}
};

template <class T1, class T2>
key_iterator<T1, T2> key_begin(std::map<T1, T2> &m)
{ return key_iterator<T1, T2>(m.begin()); }

template <class T1, class T2>
key_iterator<T1, T2> key_end(std::map<T1, T2> &m)
{ return key_iterator said:
Now, the use of those is 'key_begin(somemap)' and 'key_end(somemap)' and
they are input iterators. Is that elegant enough? Probably not. You work
on improving the elegance, I'm done.

I don't want to compare my solution with yours. But one problem can be
approached in different ways by different people and thats what I was
looking for.

Thank you for your time. I didn't wish this post to go where it went.
Its time to close it now.:)

Ram
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top