Iterator over values of std::map<K, V>

Hi all,
I have been browsing through the docs, but I couldn't find anything useful.
Does Boost have a std::map

John Kiopela wrote:
Hi all,
I have been browsing through the docs, but I couldn't find anything useful. Does Boost have a std::map
::iterator adaptor which iterates over the values of the map only. That is, I would like to have an iterator of which operator*() function returns V, instead of std::pair . My data is stored in a std::map and I would to allow my users to iterate over the values.
Off the top of my head, and untested:
typedef std::map

On 2007-11-29, John Kiopela
I have been browsing through the docs, but I couldn't find anything useful. Does Boost have a std::map
::iterator adaptor which iterates over the values of the map only.
What about using a boost::transform_iterator<>? Docs at: http://boost.org/libs/iterator/doc/transform_iterator.html You'd have to supply it with a function object that returns the 'second' member variable of the pair, e.g. struct get_pair_value { template< typename K, typename V > V operator()( std::pair< K, V > const& pr ) { return pr.second; } }; Or you could use Boost.Lambda. N.

Thanks a lot both. Transform Iterator did the trick.
Kind regards,
John
On Nov 29, 2007 9:04 PM, Niels Aan de Brugh
On 2007-11-29, John Kiopela
wrote: I have been browsing through the docs, but I couldn't find anything
Does Boost have a std::map
::iterator adaptor which iterates over useful. the
values of the map only.
What about using a boost::transform_iterator<>? Docs at:
http://boost.org/libs/iterator/doc/transform_iterator.html
You'd have to supply it with a function object that returns the 'second' member variable of the pair, e.g.
struct get_pair_value { template< typename K, typename V > V operator()( std::pair< K, V > const& pr ) { return pr.second; } };
Or you could use Boost.Lambda.
N.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

hey i am curious on the actual code you written. Cause i want to know if
doing that is faster than copying an item to a container and like iterate
over that.
template
<
class T, class U,
template
Thanks a lot both. Transform Iterator did the trick.
Kind regards,
John
On Nov 29, 2007 9:04 PM, Niels Aan de Brugh
wrote: On 2007-11-29, John Kiopela
wrote: I have been browsing through the docs, but I couldn't find anything
Does Boost have a std::map
::iterator adaptor which iterates over useful. the
values of the map only.
What about using a boost::transform_iterator<>? Docs at:
http://boost.org/libs/iterator/doc/transform_iterator.html
You'd have to supply it with a function object that returns the 'second' member variable of the pair, e.g.
struct get_pair_value { template< typename K, typename V > V operator()( std::pair< K, V > const& pr ) { return pr.second; } };
Or you could use Boost.Lambda.
N.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

I'll copy my code tomorrow, I'm not at my workstation right now. However,
I'm pretty sure that adapting the iterator is faster than copying the
values/keys into a collection in advance.
John
On 11/30/07, chun ping wang
hey i am curious on the actual code you written. Cause i want to know if doing that is faster than copying an item to a container and like iterate over that.
template < class T, class U, template
class CONT > CONT<T> getKeys(const boost::unordered_map & data) { CONT<T> retCont; typedef typename boost::unordered_map ::value_type value_type; BOOST_FOREACH(value_type val, data) { retCont.push_back(val.first); } return retCont; } Note i am using keys instead of value but concept is the same. On Nov 30, 2007 1:59 AM, John Kiopela
wrote: Thanks a lot both. Transform Iterator did the trick.
Kind regards,
John
On Nov 29, 2007 9:04 PM, Niels Aan de Brugh
wrote: On 2007-11-29, John Kiopela
wrote: I have been browsing through the docs, but I couldn't find anything
useful.
Does Boost have a std::map
::iterator adaptor which iterates over the values of the map only. What about using a boost::transform_iterator<>? Docs at:
http://boost.org/libs/iterator/doc/transform_iterator.html
You'd have to supply it with a function object that returns the 'second' member variable of the pair, e.g.
struct get_pair_value { template< typename K, typename V > V operator()( std::pair< K, V > const& pr ) { return pr.second; } };
Or you could use Boost.Lambda.
N.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Fri, Nov 30, 2007 at 10:07:19AM -0800, chun ping wang wrote:
hey i am curious on the actual code you written. Cause i want to know if doing that is faster than copying an item to a container and like iterate over that.
I'm sure there are cases when the extra copy performs better than the extra function call per element, but it'll have to be a lot of them to measure the difference. Aas an idiom however I think it's best to avoid copying if possible: for some values it may be rather expensive.
template < class T, class U, template
class CONT > CONT<T> getKeys(const boost::unordered_map & data) { CONT<T> retCont; typedef typename boost::unordered_map ::value_type value_type; BOOST_FOREACH(value_type val, data) { retCont.push_back(val.first); } return retCont; }
Modulo RVO this even copies the data twice. While we're talking iterators why not accept an output iterator as an argument, write to it and return the resulting iterator at the end (cf. std::copy)? This is more generic (the concept of an iterator is simpler and in this case closer to what you really need than the concept of a container) and more flexible, especially with the Boost iterator adapters (e.g. using the previously mentioned transform_iterator you get some kind of for_each). N.

hmm what do you mean? can you give a example.
template
<
class T, class U,
template
void getKeys(const boost::unordered_map
On Fri, Nov 30, 2007 at 10:07:19AM -0800, chun ping wang wrote:
hey i am curious on the actual code you written. Cause i want to know if doing that is faster than copying an item to a container and like iterate over that.
I'm sure there are cases when the extra copy performs better than the extra function call per element, but it'll have to be a lot of them to measure the difference. Aas an idiom however I think it's best to avoid copying if possible: for some values it may be rather expensive.
template < class T, class U, template
class CONT > CONT<T> getKeys(const boost::unordered_map & data) { CONT<T> retCont; typedef typename boost::unordered_map ::value_type value_type; BOOST_FOREACH(value_type val, data) { retCont.push_back(val.first); } return retCont; } Modulo RVO this even copies the data twice.
While we're talking iterators why not accept an output iterator as an argument, write to it and return the resulting iterator at the end (cf. std::copy)?
This is more generic (the concept of an iterator is simpler and in this case closer to what you really need than the concept of a container) and more flexible, especially with the Boost iterator adapters (e.g. using the previously mentioned transform_iterator you get some kind of for_each).
N.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On Mon, Dec 03, 2007 at 03:24:33PM -0800, chun ping wang wrote:
hmm what do you mean? can you give a example.
template < class T, class U, template
class CONT void getKeys(const boost::unordered_map
& data, const CONT<T>::iterator);
There's no need to "templatize" the container. Demanding the iterator is typedef'ed in the container is a not needed and makes the code less generic. Rather, just accept all types that model the output iterator concept and you should be fine, like so (alt.1): template< typename MapType, typename OutputIterator > OutputIterator getKeys( MapType const& map, OutputIterator out ) { for( MapType::const_iterator it = map.begin(); it != map.end(); ++it ) { *out++ = it->first; } return out; } This probably works for any type that supports the typical iteration functions and uses std::pair<>s as iterator values, e.g. std::map<>, but I haven't compiled or tested the code. Returning the iterator is useful for the caller: it can immediate call the next function with the returned iterator without having to determine how many elements you've written. This is an example just to show you what I mean in my previous mail. It would be much better to write an iterator adapter (as suggested earlier), in which case you can write the above function as a simple std::copy expression (alt.2): out = std::copy( my_iterator_adapter( map.begin() ), my_iterator_adapter( map.end() ), out ); And... you can use all the other STL algorithms (e.g. find_if) directly on the keys of your map without copying them in a container. This is not possible using alt.1. Both of the above alternatives can be used with a function_output_iterator to create an ad hoc for-all-keys-do-the-following function: void acceptKey( Key const& key ) { /* ... */ } // using alt.1 map.getKeys( boost::make_function_output_iterator( acceptKey ) ); // using alt.2 std::copy( my_iterator_adapter( map.begin() ), my_iterator_adapter( map.end() ), boost::make_function_output_iterator( acceptKey ) ); Of couse, if you chose alternative 2 you can also use std::for_each, which is probably a lot clearer to other people reading your code. There are other uses as well, such as writing to an std::ostream, or whatever. The STL is quite flexible if you use the right concepts. Note that all these applications are not possible if you use an STL container to get the keys. N.
participants (5)
-
chun ping wang
-
Jeff Flinn
-
John Kiopela
-
Niels Aan de Brugh
-
Niels Aan de Brugh