Copying from maps to lists or vectors

P

pallav

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.
 
G

Gianni Mariani

pallav said:
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.
 
M

mlimber

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
 
M

mlimber

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
 
G

Gianni Mariani

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() )
);
 
J

James Kanze

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.)
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top