Extracting keys and values in a map.

Discussion in 'C++' started by Ram, May 25, 2006.

  1. Ram

    Ram Guest

    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
    Ram, May 25, 2006
    #1
    1. Advertising

  2. 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
    Victor Bazarov, May 25, 2006
    #2
    1. Advertising

  3. Ram

    Ram Guest

    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
    Ram, May 25, 2006
    #3
  4. 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
    Victor Bazarov, May 25, 2006
    #4
  5. Ram

    Dilip Guest

    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.
    Dilip, May 25, 2006
    #5
  6. 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
    Jonathan Mcdougall, May 25, 2006
    #6
  7. 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
    Victor Bazarov, May 25, 2006
    #7
  8. 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.
    Victor Bazarov, May 25, 2006
    #8
  9. Ram

    Dilip Guest

    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?
    Dilip, May 25, 2006
    #9
  10. 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
    Jonathan Mcdougall, May 25, 2006
    #10
  11. Dilip wrote:
    > [..] What does ranting publicly buy you other than maybe
    > making you feel good for that few minutes?


    Look in the mirror, pal.
    Victor Bazarov, May 25, 2006
    #11
  12. Ram

    Ram Guest

    [...]
    > >
    > > 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::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<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
    Ram, May 26, 2006
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. sks_cpp
    Replies:
    0
    Views:
    359
    sks_cpp
    Jul 26, 2003
  2. Erik Arner
    Replies:
    0
    Views:
    1,302
    Erik Arner
    Nov 2, 2004
  3. alan
    Replies:
    3
    Views:
    348
    Victor Bazarov
    Nov 28, 2007
  4. Saeed Amrollahi

    To retrieve Keys or values of a Map

    Saeed Amrollahi, Nov 4, 2009, in forum: C++
    Replies:
    6
    Views:
    781
    gpderetta
    Nov 12, 2009
  5. Thomas E Enebo

    Map keys and values behavior

    Thomas E Enebo, Feb 8, 2005, in forum: Ruby
    Replies:
    3
    Views:
    88
    Robert Klemme
    Feb 9, 2005
Loading...

Share This Page