copy from keys from multimap into the vector

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • puzzlecracker

    #1

    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<stringve c;
    multimap<stirng , intmyMap

    // populate myMap

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

    while(iter != myMap.end())
    {
    vec.push_back(i ter->first)
    }
  • peter koch

    #2
    Re: copy from keys from multimap into the vector

    On 29 Okt., 20:33, puzzlecracker <ironsel2...@gm ail.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<stringve c;
        multimap<stirng , intmyMap
    >
       // populate myMap
    >
        multimap<string , int >::iterator iter = myMap.begin();
    >
        while(iter != myMap.end())
        {
               vec.push_back(i ter->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

    Comment

    • AnonMail2005@gmail.com

      #3
      Re: 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<stringve c;
          multimap<stirng , intmyMap
      >
         // populate myMap
      >
          multimap<string , int >::iterator iter = myMap.begin();
      >
          while(iter != myMap.end())
          {
                 vec.push_back(i ter->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.

      Comment

      • Obnoxious User

        #4
        Re: copy from keys from multimap into the vector

        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<stringve c;
        multimap<stirng , intmyMap
        >
        // populate myMap
        >
        multimap<string , int >::iterator iter = myMap.begin();
        >
        while(iter != myMap.end())
        {
        vec.push_back(i ter->first)
        }
        #include <vector>
        #include <map>
        #include <iterator>
        #include <algorithm>
        #include <iostream>

        template<typena me C, typename M>
        class key_inserter :
        public std::iterator<s td::output_iter ator_tag,void,v oid,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=(typen ame M::value_type const & p) {
        d_coll.push_bac k(p.first);
        return *this;
        }
        };

        template<typena me C, typename M>
        key_inserter<C, Mmake_key_inser ter(C & c, M & m) {
        return key_inserter<C, M>(c);
        }

        int main() {
        std::vector<int v;
        std::map<int,in tm;
        m[0];m[1];m[2];m[6];
        std::copy(m.beg in(),
        m.end(),
        make_key_insert er(v,m));
        std::copy(v.beg in(),
        v.end(),
        std::ostream_it erator<int>(std ::cout,"\n"));
        return 0;
        }

        --
        OU
        Remember 18th of June 2008, Democracy died that afternoon.


        Comment

        • peter koch

          #5
          Re: copy from keys from multimap into the vector

          On 29 Okt., 22:25, "AnonMail2...@g mail.com" <AnonMail2...@g mail.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<stringve c;
              multimap<stirng , intmyMap
          >
             // populate myMap
          >
              multimap<string , int >::iterator iter = myMap.begin();
          >
              while(iter != myMap.end())
              {
                     vec.push_back(i ter->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

          Comment

          • AnonMail2005@gmail.com

            #6
            Re: 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<stringve c;
                multimap<stirng , intmyMap
            >
               // populate myMap
            >
                multimap<string , int >::iterator iter = myMap.begin();
            >
                while(iter != myMap.end())
                {
                       vec.push_back(i ter->first)
                }
            I think this works:

            struct MyFunctor
            {
            typedef std::multimap <std::string, intStringIntMul tiMap;

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

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

            HTH

            Comment

            • Salt_Peter

              #7
              Re: copy from keys from multimap into the vector

              On Oct 29, 2:33 pm, puzzlecracker <ironsel2...@gm ail.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<stringve c;
                  multimap<stirng , intmyMap
              >
                 // populate myMap
              >
                  multimap<string , int >::iterator iter = myMap.begin();
              >
                  while(iter != myMap.end())
                  {
                         vec.push_back(i ter->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()(cons t 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_inser ter(vec),
              extract_first< VType >() );
              }

              Comment

              • puzzlecracker

                #8
                Re: copy from keys from multimap into the vector

                On Oct 29, 5:25 pm, "AnonMail2...@g mail.com" <AnonMail2...@g mail.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<stringve c;
                    multimap<stirng , intmyMap
                >
                   // populate myMap
                >
                    multimap<string , int >::iterator iter = myMap.begin();
                >
                    while(iter != myMap.end())
                    {
                           vec.push_back(i ter->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

                Comment

                • Juha Nieminen

                  #9
                  Re: copy from keys from multimap into the vector

                  Obnoxious User wrote:
                  #include <vector>
                  #include <map>
                  #include <iterator>
                  #include <algorithm>
                  #include <iostream>
                  >
                  template<typena me C, typename M>
                  class key_inserter :
                  public std::iterator<s td::output_iter ator_tag,void,v oid,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=(typen ame M::value_type const & p) {
                  d_coll.push_bac k(p.first);
                  return *this;
                  }
                  };
                  >
                  template<typena me C, typename M>
                  key_inserter<C, Mmake_key_inser ter(C & c, M & m) {
                  return key_inserter<C, M>(c);
                  }
                  >
                  int main() {
                  std::vector<int v;
                  std::map<int,in tm;
                  m[0];m[1];m[2];m[6];
                  std::copy(m.beg in(),
                  m.end(),
                  make_key_insert er(v,m));
                  std::copy(v.beg in(),
                  v.end(),
                  std::ostream_it erator<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... ;)

                  Comment

                  • Salt_Peter

                    #10
                    Re: copy from keys from multimap into the vector

                    On Oct 29, 2:33 pm, puzzlecracker <ironsel2...@gm ail.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<stringve c;
                        multimap<stirng , intmyMap
                    >
                       // populate myMap
                    >
                        multimap<string , int >::iterator iter = myMap.begin();
                    >
                        while(iter != myMap.end())
                        {
                               vec.push_back(i ter->first)
                        }
                    You could use std::transform with std::back_inser ter 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()(cons t 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_inser ter(vec),
                    extract_first< VType >() );
                    }

                    Comment

                    • Kai-Uwe Bux

                      #11
                      Re: copy from keys from multimap into the vector

                      Salt_Peter wrote:
                      On Oct 29, 2:33 pm, puzzlecracker <ironsel2...@gm ail.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<stringv ec;
                      >multimap<stirn g, intmyMap
                      >>
                      >// populate myMap
                      >>
                      >multimap<strin g, int >::iterator iter = myMap.begin();
                      >>
                      >while(iter != myMap.end())
                      >{
                      >vec.push_back( iter->first)
                      >}
                      >
                      You could use std::transform with std::back_inser ter 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()(cons t 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_inser ter(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()(cons t 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_inser ter(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

                      Comment

                      • Triple-DES

                        #12
                        Re: copy from keys from multimap into the vector

                        On 30 Okt, 01:40, Kai-Uwe Bux <jkherci...@gmx .netwrote:
                        Salt_Peter wrote:
                        You could use std::transform with std::back_inser ter 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()(cons t 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_inser ter(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()(cons t 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_inser ter(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.

                        Comment

                        • SG

                          #13
                          Re: copy from keys from multimap into the vector

                          On 30 Okt., 03:40, puzzlecracker <ironsel2...@gm ail.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_fi rst" 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

                          Comment

                          • Obnoxious User

                            #14
                            Re: copy from keys from multimap into the vector

                            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.

                            Comment

                            • James Kanze

                              #15
                              Re: copy from keys from multimap into the vector

                              On Oct 29, 8:33 pm, puzzlecracker <ironsel2...@gm ail.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<stringve c;
                              multimap<stirng , intmyMap
                              // populate myMap
                              multimap<string , int >::iterator iter = myMap.begin();
                              while(iter != myMap.end())
                              {
                              vec.push_back(i ter->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_typ e
                              result_type ;

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

                              and then:

                              typedef First< Map::value_type >
                              Mapper ;
                              typedef boost::transfor m_iterator< Mapper, Map::const_iter ator >
                              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_i terator on the
                              transform_itera tor.

                              --
                              James Kanze (GABI Software) email:james.kan ze@gmail.com
                              Conseils en informatique orientée objet/
                              Beratung in objektorientier ter Datenverarbeitu ng
                              9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                              Comment

                              Working...