[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

copy from keys from multimap into the vector

puzzlecracker

10/29/2008 7:34:00 PM

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<string> vec;
multimap<stirng, int> myMap

// populate myMap

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

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

peter koch

10/29/2008 9:02:00 PM

0

On 29 Okt., 20:33, puzzlecracker <ironsel2...@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<string> vec;
>     multimap<stirng, int> myMap
>
>    // 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_inserter(vec)); ?

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

/Peter

AnonMail2005@gmail.com

10/29/2008 9:26:00 PM

0

> > 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<string> vec;
> >     multimap<stirng, int> myMap
>
> >    // 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_inserter(vec)); ?
>
A map's element contains both the key and the value so this is not
correct.
The OP just wants the key.

Obnoxious User

10/29/2008 9:33:00 PM

0

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<string> vec;
> multimap<stirng, int> myMap
>
> // 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,void,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,M> make_key_inserter(C & c, M & m) {
return key_inserter<C,M>(c);
}

int main() {
std::vector<int> v;
std::map<int,int> m;
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_...

peter koch

10/29/2008 9:34:00 PM

0

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<string> vec;
> > >     multimap<stirng, int> myMap
>
> > >    // 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_inserter(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

AnonMail2005@gmail.com

10/29/2008 9:35:00 PM

0

> 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<string> vec;
>     multimap<stirng, int> myMap
>
>    // 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, int> StringIntMultiMap;

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

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

HTH

Salt_Peter

10/29/2008 10:08:00 PM

0

On Oct 29, 2:33 pm, puzzlecracker <ironsel2...@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<string> vec;
>     multimap<stirng, int> myMap
>
>    // 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 >() );
}

puzzlecracker

10/29/2008 10:18:00 PM

0

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<string> vec;
> > >     multimap<stirng, int> myMap
>
> > >    // 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_inserter(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

Juha Nieminen

10/29/2008 11:16:00 PM

0

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,void,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,M> make_key_inserter(C & c, M & m) {
> return key_inserter<C,M>(c);
> }
>
> int main() {
> std::vector<int> v;
> std::map<int,int> m;
> 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... ;)

Salt_Peter

10/29/2008 11:29:00 PM

0

On Oct 29, 2:33 pm, puzzlecracker <ironsel2...@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<string> vec;
>     multimap<stirng, int> myMap
>
>    // 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 >() );
}

Kai-Uwe Bux

10/30/2008 12:41:00 AM

0

Salt_Peter wrote:

> On Oct 29, 2:33 pm, puzzlecracker <ironsel2...@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<string> vec;
>> multimap<stirng, int> myMap
>>
>> // 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