Copying from maps to lists or vectors

Discussion in 'C++' started by pallav, Apr 17, 2007.

  1. pallav

    pallav Guest

    I have a map like this:

    typedef boost::shared_ptr<Node> NodePtr;
    typedef std::vector<NodePtr> NodeVecPtr;
    typedef std::map<std::string, NodePtr> NodeMap;
    typedef std::map<std:string, NodePtr>::iterator NodeMapItr;

    NodeMap nmap;

    In my classes, I often find myself copying the second arguments of
    maps to lists/vectors like this.

    NodeVecPtr nodes;
    for (NodeMapItr itr = nmap.begin(); itr != nmap.end(); ++itr)
    nodes.push_back(itr->second);

    I may also have node be a list of NodePtrs as opposed to vectors. I'm
    wondering if there is some standard STL routines, I can use to try to
    reduce this kind of code being repeated. I now std::copy() exists but
    it takes iterators. But since I'm dealing with maps, I'm not sure how
    to pass the second value as an iterator. There is also
    std::transform() but that also works with iterators.

    I've been searching the web, and found stuff like boost::bind and
    boost::iterator_adaptors that might work but I'm trying to read up the
    documentation to figure out the syntax.

    If somebody can help me in showing how I could accomplish this using
    STL/boost features, this will be helpful. Thanks for you time.
     
    pallav, Apr 17, 2007
    #1
    1. Advertising

  2. pallav wrote:
    > I have a map like this:
    >
    > typedef boost::shared_ptr<Node> NodePtr;
    > typedef std::vector<NodePtr> NodeVecPtr;
    > typedef std::map<std::string, NodePtr> NodeMap;
    > typedef std::map<std:string, NodePtr>::iterator NodeMapItr;
    >
    > NodeMap nmap;
    >
    > In my classes, I often find myself copying the second arguments of
    > maps to lists/vectors like this.
    >
    > NodeVecPtr nodes;
    > for (NodeMapItr itr = nmap.begin(); itr != nmap.end(); ++itr)
    > nodes.push_back(itr->second);


    NodeVecPtr nodes( nmap.begin(), nmap.end() );

    or

    nodes.append( nmap.begin(), nmap.end() );

    I don't know if std::list has an append method, but it does have an
    insert method that works like append.

    >
    > I may also have node be a list of NodePtrs as opposed to vectors. I'm
    > wondering if there is some standard STL routines, I can use to try to
    > reduce this kind of code being repeated. I now std::copy() exists but
    > it takes iterators. But since I'm dealing with maps, I'm not sure how
    > to pass the second value as an iterator. There is also
    > std::transform() but that also works with iterators.
    >
    > I've been searching the web, and found stuff like boost::bind and
    > boost::iterator_adaptors that might work but I'm trying to read up the
    > documentation to figure out the syntax.
    >
    > If somebody can help me in showing how I could accomplish this using
    > STL/boost features, this will be helpful. Thanks for you time.
    >
     
    Gianni Mariani, Apr 17, 2007
    #2
    1. Advertising

  3. pallav

    mlimber Guest

    On Apr 17, 4:58 pm, Gianni Mariani <> wrote:
    > pallav wrote:
    > > I have a map like this:

    >
    > > typedef boost::shared_ptr<Node> NodePtr;
    > > typedef std::vector<NodePtr> NodeVecPtr;
    > > typedef std::map<std::string, NodePtr> NodeMap;
    > > typedef std::map<std:string, NodePtr>::iterator NodeMapItr;

    >
    > > NodeMap nmap;

    >
    > > In my classes, I often find myself copying the second arguments of
    > > maps to lists/vectors like this.

    >
    > > NodeVecPtr nodes;
    > > for (NodeMapItr itr = nmap.begin(); itr != nmap.end(); ++itr)
    > > nodes.push_back(itr->second);

    >
    > NodeVecPtr nodes( nmap.begin(), nmap.end() );
    >
    > or
    >
    > nodes.append( nmap.begin(), nmap.end() );
    >
    > I don't know if std::list has an append method, but it does have an
    > insert method that works like append.


    But the map and the vector have different value_types, so this won't
    work.

    Cheers! --M
     
    mlimber, Apr 17, 2007
    #3
  4. pallav

    mlimber Guest

    On Apr 17, 2:55 pm, pallav <> wrote:
    > I have a map like this:
    >
    > typedef boost::shared_ptr<Node> NodePtr;
    > typedef std::vector<NodePtr> NodeVecPtr;
    > typedef std::map<std::string, NodePtr> NodeMap;
    > typedef std::map<std:string, NodePtr>::iterator NodeMapItr;
    >
    > NodeMap nmap;
    >
    > In my classes, I often find myself copying the second arguments of
    > maps to lists/vectors like this.
    >
    > NodeVecPtr nodes;
    > for (NodeMapItr itr = nmap.begin(); itr != nmap.end(); ++itr)
    > nodes.push_back(itr->second);
    >
    > I may also have node be a list of NodePtrs as opposed to vectors. I'm
    > wondering if there is some standard STL routines, I can use to try to
    > reduce this kind of code being repeated. I now std::copy() exists but
    > it takes iterators. But since I'm dealing with maps, I'm not sure how
    > to pass the second value as an iterator. There is also
    > std::transform() but that also works with iterators.
    >
    > I've been searching the web, and found stuff like boost::bind and
    > boost::iterator_adaptors that might work but I'm trying to read up the
    > documentation to figure out the syntax.
    >
    > If somebody can help me in showing how I could accomplish this using
    > STL/boost features, this will be helpful. Thanks for you time.


    I don't have time to work up a complete solution here, but here's a
    snippet from Karlsson's Boost book (pp. 260f):

    void print_string( const std::string& s ) {
    std::cout << s << '\n';
    }

    // ...

    std::map<int, std::string> my_map;
    my_map[0] = "Boost";
    my_map[1] = "Bind";
    std::for_each(
    my_map.begin(),
    my_map.end(),
    boost::bind( &print_string, boost::bind(
    &std::map<int,std::string>::value_type::second, _1)
    )
    );

    That should get you started.

    Cheers! --M
     
    mlimber, Apr 17, 2007
    #4
  5. mlimber wrote:
    > On Apr 17, 4:58 pm, Gianni Mariani <> wrote:
    >> pallav wrote:


    > But the map and the vector have different value_types, so this won't
    > work.


    Ya - missed that one.

    OK - how about an interator that derefs to the second element ?


    psuedo code :

    template <typename T>
    struct second_iterator
    {

    T m_iterator;

    second_iterator( const T& i_iterator );

    typename T::second_type & operator*()
    {
    return m_iterator->second;
    }

    ....
    };

    template <typename T>
    second_iterator<T> make_second_iterator( const T & i_iterator )
    {
    return second_iterator<T>( i_iterator );
    }

    .... and then you can write:

    NodeVecPtr nodes(
    make_second_iterator( nmap.begin() ),
    make_second_iterator( nmap.end() )
    );
     
    Gianni Mariani, Apr 17, 2007
    #5
  6. pallav

    James Kanze Guest

    On Apr 17, 8:55 pm, pallav <> wrote:
    > I have a map like this:


    > typedef boost::shared_ptr<Node> NodePtr;
    > typedef std::vector<NodePtr> NodeVecPtr;
    > typedef std::map<std::string, NodePtr> NodeMap;
    > typedef std::map<std:string, NodePtr>::iterator NodeMapItr;


    > NodeMap nmap;


    > In my classes, I often find myself copying the second arguments of
    > maps to lists/vectors like this.


    > NodeVecPtr nodes;
    > for (NodeMapItr itr = nmap.begin(); itr != nmap.end(); ++itr)
    > nodes.push_back(itr->second);


    > I may also have node be a list of NodePtrs as opposed to vectors. I'm
    > wondering if there is some standard STL routines, I can use to try to
    > reduce this kind of code being repeated. I now std::copy() exists but
    > it takes iterators. But since I'm dealing with maps, I'm not sure how
    > to pass the second value as an iterator. There is also
    > std::transform() but that also works with iterators.


    > I've been searching the web, and found stuff like boost::bind and
    > boost::iterator_adaptors that might work but I'm trying to read up the
    > documentation to figure out the syntax.


    > If somebody can help me in showing how I could accomplish this using
    > STL/boost features, this will be helpful. Thanks for you time.


    Wouldn't something like the following work:

    template< typename Map >
    struct ValueFromMap
    : public std::unary_function< typename Map::value_type,
    typename Map::mapped_type >
    {
    typename Map::mapped_type operator()(
    typename Map::value_type const&
    elem ) const
    {
    return elem.second ;
    }
    } ;

    typedef boost::transform_iterator< ValueFromMap< NodeMap >,
    NodeMap::const_iterator >
    ValueIter ;

    (I tried it with a std::map< std::string, int >, and it seemed
    to work.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 18, 2007
    #6
    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. Fred Ma
    Replies:
    15
    Views:
    641
    Fred Ma
    Jan 30, 2004
  2. Simon Elliott
    Replies:
    4
    Views:
    1,173
    Simon Elliott
    Mar 10, 2005
  3. Sheep
    Replies:
    1
    Views:
    397
    Sheep
    Aug 14, 2006
  4. LeTubs
    Replies:
    1
    Views:
    300
    Jonathan Mcdougall
    Dec 5, 2005
  5. Marcus
    Replies:
    2
    Views:
    598
    Marcus
    Dec 9, 2005
Loading...

Share This Page