Re: Multimap: how to get a key list?
On 2 mar, 01:35, "Daniel T." <danie...@earthlink.net> wrote:
In article
<d0b0d95f-293e-4556-a824-b96a9ebb8...@15g2000yqi.googlegroups.com>,
Brian <c...@mailvault.com> wrote:
On Feb 28, 5:09 pm, Sam <s...@email-scan.com> wrote:
Rui Maciel writes:
Is there any way to get a list of keys from a multimap besides rely=
ing on
a couple of nested
loops to assemble that list?
What nested loops? Only one loop is required to iterate over the mult=
imap.
There is no single function that gives you a set of all keys stored i=
n the
multimap, but a single loop is all that's needed to retrieve all the =
keys.
It's fairly easy to define a template function that gives them to you=
,
something like this:
template<typename multimap_t>
void keys(const multimap_t &m,
std::set<typename multimap_t::key_type> &k)
{
for (typename multimap_t::const_iterator b(m.begin()), e(m.en=
d());
b != e; ++b)
{
k.insert(b->first);
}
}
The std::set automatically takes care of deduping the multimap's keys=
..
I think that works fine. This might speed it up a little:
template<typename multimap_t>
void keys(const multimap_t &m,
std::set<typename multimap_t::key_type> &k)
{
typename std::set<typename multimap_t::key_type>::iterator
keys_end = k.end();
for (typename multimap_t::const_iterator b(m.begin()),
e(m.end());
b != e; ++b)
{
k.insert(keys_end, b->first);
}
}
That would work best if k is being passed in
as an empty container as seems likely.
Now that I understand the question I can give a better answer than I did
the first time around...
Using the code below, you don't have to insert into a set, you can
insert into any output iterator (of course all of these examples work
with both multimaps and regular maps:
template < typename map_t, typename OutIt>
void keys(const map_t& aMap, OutIt out)
{
for (typename map_t::const_iterator it = aMap.begin();
it != aMap.end();
it = aMap.upper_bound(it->first))
out++ = it->first;
}
[snip]
Another solution is to use decoration:
template<typename iterator_type>
class key_iterator:
std::iterator< typename iterator_type::iterator_category
// return type of iterator is key type
, typename iterator_type::value_type::first_type
, typename iterator_type::difference_type
>
{
public:
// put here the typedefs iterator_category, ...
// build from
key_iterator(const iterator_type& i):it(i){}
// usual operation on iterator
key_iterator& operator++()
{ ++it;return *this;}
view_iterator operator++(int)
{ return key_iterator(it++);}
bool operator == (const key_iterator& rhs) const
{return it == rhs.it;}
// and so on for other iterator operations
// return key
reference operator*() const
{return it->first; }
pointer operator->() const
{return &it->first; }
private:
iterator_type it;
};
And then you can use
template<class T>
key_iterator<typename T::iterator_type> key_begin(T& container)
{
return container.begin();
}
template<class T>
key_iterator<typename T::iterator_type> key_end(T& container)
{
return container.end();
}
You can do whatever you want on the keys of an associative container.
std::accumulate(key_begin(aMap),key_end(aMap), 0 );
--
Michael