470,864 Members | 1,989 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,864 developers. It's quick & easy.

Extracting keys and values in a map.

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

May 25 '06 #1
11 2550
Ram wrote:
[..]
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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
May 25 '06 #2
Ram
Victor Bazarov wrote:
Ram wrote:
[..]
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.
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. 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

May 25 '06 #3
Ram wrote:
Victor Bazarov wrote:
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:
-------------------
#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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
May 25 '06 #4
Victor Bazarov wrote:
Ram wrote:
Victor Bazarov wrote:
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.

May 25 '06 #5
Victor Bazarov wrote:
Ram wrote:
Victor Bazarov wrote:
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:


<snip code example>
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

May 25 '06 #6
Dilip wrote:
[..]
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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
May 25 '06 #7
Jonathan Mcdougall wrote:
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.
May 25 '06 #8
Victor Bazarov wrote:
Dilip wrote:
[..]
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.
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.


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?

May 25 '06 #9
Victor Bazarov wrote:
Jonathan Mcdougall wrote:
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.


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

May 25 '06 #10
Dilip wrote:
[..] What does ranting publicly buy you other than maybe
making you feel good for that few minutes?


Look in the mirror, pal.
May 25 '06 #11
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:
-------------------
#include <map> [...] -------------------
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::operator*().first; }

pointer operator->() const
{ return &(base_t::operator*().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<T1, T2>(m.end()); }
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

May 26 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

16 posts views Thread by Preben Randhol | last post: by
13 posts views Thread by Nader | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.