472,143 Members | 1,370 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,143 software developers and data experts.

copy from keys from multimap into the vector

I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.

Here is what I do and would like to if someone has a cleaner solution:

vector<stringvec;
multimap<stirng, intmyMap

// populate myMap

multimap<string, int >::iterator iter = myMap.begin();

while(iter != myMap.end())
{
vec.push_back(iter->first)
}
Oct 29 '08 #1
20 3810
On 29 Okt., 20:33, puzzlecracker <ironsel2...@gmail.comwrote:
I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.

Here is what I do and would like to if someone has a cleaner solution:

* * vector<stringvec;
* * multimap<stirng, intmyMap

* *// populate myMap

* * multimap<string, int >::iterator iter = myMap.begin();

* * while(iter != myMap.end())
* * {
* * * * * *vec.push_back(iter->first)
* * }
Whats wrong with
std::copy(myMap.begin(),myMap.end(),std::back_inse rter(vec)); ?

You could do a reserve on vec first to improve performance.

/Peter
Oct 29 '08 #2
I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.
Here is what I do and would like to if someone has a cleaner solution:
* * vector<stringvec;
* * multimap<stirng, intmyMap
* *// populate myMap
* * multimap<string, int >::iterator iter = myMap.begin();
* * while(iter != myMap.end())
* * {
* * * * * *vec.push_back(iter->first)
* * }

Whats wrong with
std::copy(myMap.begin(),myMap.end(),std::back_inse rter(vec)); ?
A map's element contains both the key and the value so this is not
correct.
The OP just wants the key.
Oct 29 '08 #3
On Wed, 29 Oct 2008 12:33:38 -0700, puzzlecracker wrote:
I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.

Here is what I do and would like to if someone has a cleaner solution:

vector<stringvec;
multimap<stirng, intmyMap

// populate myMap

multimap<string, int >::iterator iter = myMap.begin();

while(iter != myMap.end())
{
vec.push_back(iter->first)
}
#include <vector>
#include <map>
#include <iterator>
#include <algorithm>
#include <iostream>

template<typename C, typename M>
class key_inserter :
public std::iterator<std::output_iterator_tag,void,void,v oid,void{
private:
C & d_coll;
public:
key_inserter(C & c) : d_coll(c) {}
key_inserter & operator*() { return *this; }
key_inserter & operator++() { return *this; }
key_inserter & operator++(int) { return *this; }
key_inserter &
operator=(typename M::value_type const & p) {
d_coll.push_back(p.first);
return *this;
}
};

template<typename C, typename M>
key_inserter<C,Mmake_key_inserter(C & c, M & m) {
return key_inserter<C,M>(c);
}

int main() {
std::vector<intv;
std::map<int,intm;
m[0];m[1];m[2];m[6];
std::copy(m.begin(),
m.end(),
make_key_inserter(v,m));
std::copy(v.begin(),
v.end(),
std::ostream_iterator<int>(std::cout,"\n"));
return 0;
}

--
OU
Remember 18th of June 2008, Democracy died that afternoon.
http://frapedia.se/wiki/Information_in_English

Oct 29 '08 #4
On 29 Okt., 22:25, "AnonMail2...@gmail.com" <AnonMail2...@gmail.com>
wrote:
I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.
Here is what I do and would like to if someone has a cleaner solution:
* * vector<stringvec;
* * multimap<stirng, intmyMap
* *// populate myMap
* * multimap<string, int >::iterator iter = myMap.begin();
* * while(iter != myMap.end())
* * {
* * * * * *vec.push_back(iter->first)
* * }
Whats wrong with
std::copy(myMap.begin(),myMap.end(),std::back_inse rter(vec)); ?

A map's element contains both the key and the value so this is not
correct.
The OP just wants the key.
I did not see that. Don't ask the question in the title (but read the
title anyway!).
In that case, I'd recommend having a look at Boosts iterator adaptors
which should do the job. But I admit that I haven't looked at that
part of Boost for a while (and never used it).

/Peter
Oct 29 '08 #5
I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.

Here is what I do and would like to if someone has a cleaner solution:

* * vector<stringvec;
* * multimap<stirng, intmyMap

* *// populate myMap

* * multimap<string, int >::iterator iter = myMap.begin();

* * while(iter != myMap.end())
* * {
* * * * * *vec.push_back(iter->first)
* * }
I think this works:

struct MyFunctor
{
typedef std::multimap <std::string, intStringIntMultiMap;

std::string operator () (StringIntMultiMap::value_type const & v)
const
{
return v.first;
}
};

std::transform (myMap.begin (), myMap.end (), back_inserter (vec),
MyFunctor ());

HTH
Oct 29 '08 #6
On Oct 29, 2:33*pm, puzzlecracker <ironsel2...@gmail.comwrote:
I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.

Here is what I do and would like to if someone has a cleaner solution:

* * vector<stringvec;
* * multimap<stirng, intmyMap

* *// populate myMap

* * multimap<string, int >::iterator iter = myMap.begin();

* * while(iter != myMap.end())
* * {
* * * * * *vec.push_back(iter->first)
* * }
You'll need a functor to extract that string from multimap's
value_type and std::transform can process the elements.

#include <iostream>
#include <ostream>
#include <string>
#include <vector>
#include <map>
#include <iterator>

template< typename P >
struct extract_first
{
const typename P::first_type&
operator()(const P& p) const
{
return p.first;
}
};

int main()
{
std::vector< std::string vec;
std::multimap< std::string, int mm;

// populate mm

typedef std::multimap< std::string, int >::value_type VType;

std::transform( mm.begin(),
mm.end(),
std::back_inserter(vec),
extract_first< VType >() );
}
Oct 29 '08 #7
On Oct 29, 5:25*pm, "AnonMail2...@gmail.com" <AnonMail2...@gmail.com>
wrote:
I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.
Here is what I do and would like to if someone has a cleaner solution:
* * vector<stringvec;
* * multimap<stirng, intmyMap
* *// populate myMap
* * multimap<string, int >::iterator iter = myMap.begin();
* * while(iter != myMap.end())
* * {
* * * * * *vec.push_back(iter->first)
* * }
Whats wrong with
std::copy(myMap.begin(),myMap.end(),std::back_inse rter(vec)); ?

A map's element contains both the key and the value so this is not
correct.
The OP just wants the key.
Exactly... that's not going to work, I don't need the value_key, which
is pair<string, int>

Thanks
Oct 29 '08 #8
Obnoxious User wrote:
#include <vector>
#include <map>
#include <iterator>
#include <algorithm>
#include <iostream>

template<typename C, typename M>
class key_inserter :
public std::iterator<std::output_iterator_tag,void,void,v oid,void{
private:
C & d_coll;
public:
key_inserter(C & c) : d_coll(c) {}
key_inserter & operator*() { return *this; }
key_inserter & operator++() { return *this; }
key_inserter & operator++(int) { return *this; }
key_inserter &
operator=(typename M::value_type const & p) {
d_coll.push_back(p.first);
return *this;
}
};

template<typename C, typename M>
key_inserter<C,Mmake_key_inserter(C & c, M & m) {
return key_inserter<C,M>(c);
}

int main() {
std::vector<intv;
std::map<int,intm;
m[0];m[1];m[2];m[6];
std::copy(m.begin(),
m.end(),
make_key_inserter(v,m));
std::copy(v.begin(),
v.end(),
std::ostream_iterator<int>(std::cout,"\n"));
return 0;
}
Given that the while loop solution only requires 2 lines of code, I
think it's the easier solution... ;)
Oct 29 '08 #9
On Oct 29, 2:33*pm, puzzlecracker <ironsel2...@gmail.comwrote:
I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.

Here is what I do and would like to if someone has a cleaner solution:

* * vector<stringvec;
* * multimap<stirng, intmyMap

* *// populate myMap

* * multimap<string, int >::iterator iter = myMap.begin();

* * while(iter != myMap.end())
* * {
* * * * * *vec.push_back(iter->first)
* * }
You could use std::transform with std::back_inserter to load vector
and a functor to extract the std::string from multimap's value_type.

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>

template< typename P >
struct extract_first
{
const typename P::first_type&
operator()(const P& p) const
{
return p.first;
}
};

int main()
{
std::vector< std::string vec;
std::multimap< std::string, int mm;
// populate mm

typedef std::multimap< std::string, int >::value_type VType;

std::transform( mm.begin(),
mm.end(),
std::back_inserter(vec),
extract_first< VType >() );
}
Oct 29 '08 #10
Salt_Peter wrote:
On Oct 29, 2:33*pm, puzzlecracker <ironsel2...@gmail.comwrote:
>I am using while loop for that but I am sure you can do it quicker and
more syntactically clear with copy function.

Here is what I do and would like to if someone has a cleaner solution:

vector<stringvec;
multimap<stirng, intmyMap

// populate myMap

multimap<string, int >::iterator iter = myMap.begin();

while(iter != myMap.end())
{
vec.push_back(iter->first)
}

You could use std::transform with std::back_inserter to load vector
and a functor to extract the std::string from multimap's value_type.

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>

template< typename P >
struct extract_first
{
const typename P::first_type&
operator()(const P& p) const
{
return p.first;
}
};

int main()
{
std::vector< std::string vec;
std::multimap< std::string, int mm;
// populate mm

typedef std::multimap< std::string, int >::value_type VType;

std::transform( mm.begin(),
mm.end(),
std::back_inserter(vec),
extract_first< VType >() );
}
Alternatively, one can put the template inside:

// same headers

struct extract_first {

template< typename P >
typename P::first_type const &
operator()(const P& p) const {
return p.first;
}

};

int main() {
std::vector< std::string vec;
std::multimap< std::string, int mm;
// populate mm

std::transform( mm.begin(),
mm.end(),
std::back_inserter(vec),
extract_first() );
}

This makes extract_first oblivious to the type actually being used. I am not
sure, which is better. Any thoughts?
Best

Kai-Uwe Bux
Oct 30 '08 #11
On 30 Okt, 01:40, Kai-Uwe Bux <jkherci...@gmx.netwrote:
Salt_Peter wrote:
You could use std::transform with std::back_inserter to load vector
and a functor to extract the std::string from multimap's value_type.
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>
template< typename P >
struct extract_first
{
* const typename P::first_type&
* operator()(const P& p) const
* {
* * return p.first;
* }
};
int main()
{
* std::vector< std::string vec;
* std::multimap< std::string, int mm;
* // populate mm
* typedef std::multimap< std::string, int >::value_type VType;
* std::transform( mm.begin(),
* * * * * * * * * mm.end(),
* * * * * * * * * std::back_inserter(vec),
* * * * * * * * * extract_first< VType >() );
}

Alternatively, one can put the template inside:

// same headers

struct extract_first {

* template< typename P >
* typename P::first_type const &
* operator()(const P& p) const {
* * return p.first;
* }

};

int main() {
* std::vector< std::string vec;
* std::multimap< std::string, int mm;
* // populate mm

* std::transform( mm.begin(),
* * * * * * * * * mm.end(),
* * * * * * * * * std::back_inserter(vec),
* * * * * * * * * extract_first() );

}

This makes extract_first oblivious to the type actually being used. I am not
sure, which is better. Any thoughts?
I like your solution, but the "canonical" solution, I think, is the
former (looking at SGI's select1st functor). That being said, I can't
think of a case where your solution would be any worse.
Oct 30 '08 #12
SG
On 30 Okt., 03:40, puzzlecracker <ironsel2...@gmail.comwrote:
Given that the while loop solution only requires 2 lines of code, I
think it's the easier solution... ;)

That's exactly my point. Guys, do you see how this solution is
verbose, cluttered, and not particularly expressive over my
traditional solution?
Well, the "extract_first" functor is reusable. You only have to write
it down once. Your problem is solved with one function call. Also, I
like the fact that Kai-Uwe's solution is NOT cluttered with names of
types (iterator, value_type, ...). In the upcoming C++ version I would
probably prefer the new for-range construct along with type inference
to avoid this:

#include <for>
:
for (auto & p : mymultimap) myvector.push(p.first);
:

This will also avoid the creation of a temporary copy of pair.first
because operator() in extract_first returns a copy. Of course you
could define this function to return a const reference and I think
this will be ok in this situation because the pair reference is NOT a
temporary. But it may lead to danling references in other cases. So,
coding your own loop is more efficient.

Cheers,
SG
Oct 30 '08 #13
On Wed, 29 Oct 2008 23:15:35 +0000, Juha Nieminen wrote:
Obnoxious User wrote:
[snip]
>
Given that the while loop solution only requires 2 lines of code, I
think it's the easier solution... ;)
On the other hand, if this action is required in multiple
places, then I would prefer some sort of abstraction instead
of a simple while loop.

--
OU
Remember 18th of June 2008, Democracy died that afternoon.
http://frapedia.se/wiki/Information_in_English
Oct 30 '08 #14
On Oct 29, 8:33 pm, puzzlecracker <ironsel2...@gmail.comwrote:
I am using while loop for that but I am sure you can do it
quicker and more syntactically clear with copy function.
Here is what I do and would like to if someone has a cleaner
solution:
vector<stringvec;
multimap<stirng, intmyMap
// populate myMap
multimap<string, int >::iterator iter = myMap.begin();
while(iter != myMap.end())
{
vec.push_back(iter->first)
}
Do you really want multiple entries in the vector when there are
multiple entries for a single key in the map? If so, something
like the following should work:

template< typename Pair >
struct First
{
typedef Pair argument_type ;
typedef typename Pair::first_type
result_type ;

typename Pair::first_type
operator()( Pair const& obj ) const
{
return obj.first ;
}
} ;

and then:

typedef First< Map::value_type >
Mapper ;
typedef boost::transform_iterator< Mapper, Map::const_iterator >
InitIter ;
std::vector< std::string >
k( InitIter( m.begin(), Mapper() ),
InitIter( m.end(), Mapper() ) ) ;

If you only want each unique key to appear once, then you should
be able to use a boost::filter_iterator on the
transform_iterator.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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
Oct 30 '08 #15
On Oct 30, 12:15 am, Juha Nieminen <nos...@thanks.invalidwrote:
Given that the while loop solution only requires 2 lines of
code, I think it's the easier solution... ;)
But it isn't kool, or in:-).

A lot depends on context. If you often have code which can use
the standard algorithms, provided you can map to only the key or
the mapped type, then it's worth writing functional objects
which do this mapping, and using boost::transform_iterator as
arguments to the constructor. For a one of use, on the other
hand, it's really a question of why be simple, when you can be
complicated. Unless, of course, your goal is mainly to show
off.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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

Oct 30 '08 #16
On Oct 30, 3:40 am, puzzlecracker <ironsel2...@gmail.comwrote:
Given that the while loop solution only requires 2 lines of
code, I think it's the easier solution... ;)
That's exactly my point. Guys, do you see how this solution
is verbose, cluttered, and not particularly expressive over my
traditional solution? Meyers allegedly encourages to use
transforms, copy and other algorithms in the STL library. And
I am confident that for this problem, he would still pick a
stl-like solution. However, using transform, in this case,
doesn't telegraph your intent
It doesn't. You're transforming the values of a map into
strings (or whatever).

This merits a half a :-). I actually agree with you. But
mainly because despite the contortions of the standard library;
a map conceptually isn't a "container" of objects, but has keys
and values. And you don't want to transform the keys, just copy
them. If you think of a map as a container of key-value pairs,
which is how the standard library views it, then you are
transforming a key-value pair into a key.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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
Oct 30 '08 #17
On Oct 30, 12:23*pm, James Kanze <james.ka...@gmail.comwrote:
On Oct 30, 3:40 am, puzzlecracker <ironsel2...@gmail.comwrote:
Given that the while loop solution only requires 2 lines of
code, I think it's the easier solution... ;)
That's exactly my point. *Guys, do you see how this solution
is verbose, cluttered, and not particularly expressive over my
traditional solution? *Meyers allegedly encourages to use
transforms, copy and other algorithms in the STL library. And
I am confident that for this problem, he would still pick a
stl-like solution. However, using transform, in this case,
doesn't telegraph your intent

It doesn't. *You're transforming the values of a map into
strings (or whatever).

This merits a half a :-). *I actually agree with you. *But
mainly because despite the contortions of the standard library;
a map conceptually isn't a "container" of objects, but has keys
and values. *And you don't want to transform the keys, just copy
them. *If you think of a map as a container of key-value pairs,
which is how the standard library views it, then you are
transforming a key-value pair into a key.
You can also think of an std::map as relation (in the relational
algebra sense). In this model transform is equivalent to the
projection operation. Boost.Multimap makes the model more explicit,
but it also works well for standard associative containers.

--
gpd
Oct 30 '08 #18
On Oct 30, 7:23*am, James Kanze <james.ka...@gmail.comwrote:
On Oct 30, 3:40 am, puzzlecracker <ironsel2...@gmail.comwrote:
Given that the while loop solution only requires 2 lines of
code, I think it's the easier solution... ;)
That's exactly my point. *Guys, do you see how this solution
is verbose, cluttered, and not particularly expressive over my
traditional solution? *Meyers allegedly encourages to use
transforms, copy and other algorithms in the STL library. And
I am confident that for this problem, he would still pick a
stl-like solution. However, using transform, in this case,
doesn't telegraph your intent

It doesn't. *You're transforming the values of a map into
strings (or whatever).

This merits a half a :-). *I actually agree with you. *But
mainly because despite the contortions of the standard library;
a map conceptually isn't a "container" of objects, but has keys
and values. *And you don't want to transform the keys, just copy
them. *If you think of a map as a container of key-value pairs,
which is how the standard library views it, then you are
transforming a key-value pair into a key.

--
James Kanze (GABI Software) * * * * * * email:james.ka...@gmail.com
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, you're essentially supporting my asserting not only in regard
to my example, but STL in general. Even though STL solves a lot of
computational problems, but it does in fact has a tendency to
introduce maintenance and readability nightmare.

Boost, ah, we don't use it in our shop.

Is there a list of companies who use Boost ?

Thanks
Oct 30 '08 #19
On Oct 30, 7:23*am, James Kanze <james.ka...@gmail.comwrote:
On Oct 30, 3:40 am, puzzlecracker <ironsel2...@gmail.comwrote:
Given that the while loop solution only requires 2 lines of
code, I think it's the easier solution... ;)
That's exactly my point. *Guys, do you see how this solution
is verbose, cluttered, and not particularly expressive over my
traditional solution? *Meyers allegedly encourages to use
transforms, copy and other algorithms in the STL library. And
I am confident that for this problem, he would still pick a
stl-like solution. However, using transform, in this case,
doesn't telegraph your intent

It doesn't. *You're transforming the values of a map into
strings (or whatever).

This merits a half a :-). *I actually agree with you. *But
mainly because despite the contortions of the standard library;
a map conceptually isn't a "container" of objects, but has keys
and values. *And you don't want to transform the keys, just copy
them. *If you think of a map as a container of key-value pairs,
which is how the standard library views it, then you are
transforming a key-value pair into a key.

--
James Kanze (GABI Software) * * * * * * email:james.ka...@gmail.com
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, you're essentially supporting the claim not only in regard
to my example, but STL in general. Even though STL solves a lot of
computational problems, it does in fact has a tendency to
introduce maintenance and readability nightmare.

Boost, ah, we don't use it in our shop.

Is there a list of companies who use Boost ?

Thanks
Oct 30 '08 #20
On Oct 30, 7:23*am, James Kanze <james.ka...@gmail.comwrote:
On Oct 30, 3:40 am, puzzlecracker <ironsel2...@gmail.comwrote:
Given that the while loop solution only requires 2 lines of
code, I think it's the easier solution... ;)
That's exactly my point. *Guys, do you see how this solution
is verbose, cluttered, and not particularly expressive over my
traditional solution? *Meyers allegedly encourages to use
transforms, copy and other algorithms in the STL library. And
I am confident that for this problem, he would still pick a
stl-like solution. However, using transform, in this case,
doesn't telegraph your intent

It doesn't. *You're transforming the values of a map into
strings (or whatever).

This merits a half a :-). *I actually agree with you. *But
mainly because despite the contortions of the standard library;
a map conceptually isn't a "container" of objects, but has keys
and values. *And you don't want to transform the keys, just copy
them. *If you think of a map as a container of key-value pairs,
which is how the standard library views it, then you are
transforming a key-value pair into a key.

--
James Kanze (GABI Software) * * * * * * email:james.ka...@gmail.com
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, you're essentially supporting the claim not only in regard
to my example, but STL in general. Even though STL solves a lot of
computational problems, it does in fact have a tendency to
introduce maintenance and readability nightmare.

Boost, ah, we don't use it in our shop.

Is there a list of companies who use Boost ?

Thanks
Oct 30 '08 #21

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by al | last post: by
3 posts views Thread by Przemek | last post: by
4 posts views Thread by Nick Keighley | last post: by
2 posts views Thread by Tommo | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.