To retrieve Keys or values of a Map

Discussion in 'C++' started by Saeed Amrollahi, Nov 4, 2009.

  1. Dear all

    I have a question. Is there any generic algorithm or solution to
    access the keys or values
    of a map? I frequently face to such problem and I usually write a
    function to copy
    the keys/values of a map into a container let say a vector.

    Many thanks, in advance, for your help.
     
    Saeed Amrollahi, Nov 4, 2009
    #1
    1. Advertising

  2. Saeed Amrollahi wrote:
    > Dear all
    >
    > I have a question. Is there any generic algorithm or solution to
    > access the keys or values
    > of a map? I frequently face to such problem and I usually write a
    > function to copy
    > the keys/values of a map into a container let say a vector.
    >
    > Many thanks, in advance, for your help.


    I've written a utility roughly like this:

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

    namespace {
    template <typename T1, typename T2>
    const T1& take_first(const typename std::map<T1,T2>::value_type& pair) {
    return pair.first;
    }
    }

    template <typename T1, typename T2>
    std::list<T1> keys(const std::map<T1,T2>& in) {
    std::list<T1> klist(in.size());
    std::transform(in.begin(), in.end(), klist.begin(), take_first<T1,T2>);
    return klist;
    }

    int main() {
    std::map<std::string, int> map;
    map["test"] = 0;
    map["test2"] = 0;

    const std::list<std::string>& keys = ::keys(map);
    std::copy(keys.begin(), keys.end(),
    std::eek:stream_iterator<std::string>(std::cout, "\n"));

    return 0;
    }

    Although this isn't exactly ideal, and would be a nice place to use a
    lambda function in C++0x too.

    There's a few annoying things about this though, the function take_first
    has to live inside the anonymous namespace because it's not legal to
    write the following, which given the absence of lambda functions would
    be cleaner in my view:

    template <typename T1, typename T2>
    std::list<T1> keys(const std::map<T1,T2>& in) {
    struct {
    const T1& operator()(const typename std::map<T1,T2>::value_type&
    pair) {
    return pair.first;
    }
    } take_first;

    std::list<T1> klist(in.size());
    std::transform(in.begin(), in.end(), klist.begin(), take_first);
    return klist;
    }

    I also never got type deduction for the function pointer argument to
    std::transform to work, which I kind of expected it would, although
    that's not exactly a problem.

    Alan
     
    Alan Woodland, Nov 4, 2009
    #2
    1. Advertising

  3. On Nov 4, 3:05 pm, Alan Woodland <> wrote:
    > Saeed Amrollahi wrote:
    > > Dear all

    >
    > > I have a question. Is there any generic algorithm or solution to
    > > access the keys or values
    > > of a map? I frequently face to such problem and I usually write a
    > > function to copy
    > > the keys/values of a map into a container let say a vector.

    >
    > > Many thanks, in advance, for your help.

    >
    > I've written a utility roughly like this:
    >
    > #include <string>
    > #include <algorithm>
    > #include <iostream>
    > #include <list>
    > #include <map>
    > #include <iterator>
    >
    > namespace {
    >    template <typename T1, typename T2>
    >    const T1& take_first(const typename std::map<T1,T2>::value_type& pair) {
    >      return pair.first;
    >    }
    >
    > }
    >
    > template <typename T1, typename T2>
    > std::list<T1> keys(const std::map<T1,T2>& in) {
    >    std::list<T1> klist(in.size());
    >    std::transform(in.begin(), in.end(), klist.begin(), take_first<T1,T2>);
    >    return klist;
    >
    > }
    >
    > int main() {
    >    std::map<std::string, int> map;
    >    map["test"] = 0;
    >    map["test2"] = 0;
    >
    >    const std::list<std::string>& keys = ::keys(map);
    >    std::copy(keys.begin(), keys.end(),
    > std::eek:stream_iterator<std::string>(std::cout, "\n"));
    >
    >    return 0;
    >
    > }
    >
    > Although this isn't exactly ideal, and would be a nice place to use a
    > lambda function in C++0x too.
    >
    > There's a few annoying things about this though, the function take_first
    > has to live inside the anonymous namespace because it's not legal to
    > write the following, which given the absence of lambda functions would
    > be cleaner in my view:
    >
    > template <typename T1, typename T2>
    > std::list<T1> keys(const std::map<T1,T2>& in) {
    >    struct {
    >      const T1& operator()(const typename std::map<T1,T2>::value_type&
    > pair) {
    >        return pair.first;
    >      }
    >    } take_first;
    >
    >    std::list<T1> klist(in.size());
    >    std::transform(in.begin(), in.end(), klist.begin(), take_first);
    >    return klist;
    >
    > }
    >
    > I also never got type deduction for the function pointer argument to
    > std::transform to work, which I kind of expected it would, although
    > that's not exactly a problem.
    >
    > Alan


    Hi Alan

    Thank you for your code. It is really good. It is better than my code
    and I definitely will use it.
    So, there is no pre-built generic algorithm for doing this.

    Thanks again,
    -- Saeed Amrollahi
     
    Saeed Amrollahi, Nov 5, 2009
    #3
  4. Saeed Amrollahi

    mzdude Guest

    On Nov 4, 4:44 am, Saeed Amrollahi <> wrote:
    > Dear all
    >
    > I have a question. Is there any generic algorithm or solution to
    > access the keys or values
    > of a map? I frequently face to such problem and I usually write a
    > function to copy
    > the keys/values of a map into a container let say a vector.
    >
    > Many thanks, in advance, for your help.


    #include <string>
    #include <iterator>
    #include <boost/foreach.hpp>
    #include <iostream>
    #include <list>
    #include <map>

    typedef std::map<std::wstring,std::wstring> MyMapType;
    typedef std::pair<std::wstring,std::wstring> MapPairType;

    MyMapType MyMap;

    template<typename U>
    std::list<typename U::key_type> getKeys(U const &m)
    {
    typedef std::pair<typename U::key_type,typename U::mapped_type>
    PairType;

    std::list<typename U::key_type> tempList;
    BOOST_FOREACH(PairType const &i,m)
    tempList.push_back(i.first);
    return tempList;
    }

    int main()
    {
    MyMap[L"one"] = L"Hello World";
    MyMap[L"two"] = L"Another string";

    std::list<std::wstring> myList = getKeys(MyMap);

    BOOST_FOREACH(std::wstring &i,myList)
    std::wcout << i << L"\n";

    return 0;
    }
     
    mzdude, Nov 5, 2009
    #4
  5. On Nov 5, 5:30 pm, mzdude <> wrote:
    > On Nov 4, 4:44 am, Saeed Amrollahi <> wrote:
    >
    > > Dear all

    >
    > > I have a question. Is there any generic algorithm or solution to
    > > access the keys or values
    > > of a map? I frequently face to such problem and I usually write a
    > > function to copy
    > > the keys/values of a map into a container let say a vector.

    >
    > > Many thanks, in advance, for your help.

    >
    > #include <string>
    > #include <iterator>
    > #include <boost/foreach.hpp>
    > #include <iostream>
    > #include <list>
    > #include <map>
    >
    > typedef std::map<std::wstring,std::wstring> MyMapType;
    > typedef std::pair<std::wstring,std::wstring> MapPairType;
    >
    > MyMapType MyMap;
    >
    > template<typename U>
    > std::list<typename U::key_type> getKeys(U const &m)
    > {
    >    typedef std::pair<typename U::key_type,typename U::mapped_type>
    > PairType;
    >
    >    std::list<typename U::key_type> tempList;
    >    BOOST_FOREACH(PairType const &i,m)
    >       tempList.push_back(i.first);
    >    return tempList;
    >
    > }
    >
    > int main()
    > {
    >    MyMap[L"one"] = L"Hello World";
    >    MyMap[L"two"] = L"Another string";
    >
    >    std::list<std::wstring> myList = getKeys(MyMap);
    >
    >    BOOST_FOREACH(std::wstring &i,myList)
    >       std::wcout << i << L"\n";
    >
    >    return 0;
    >
    >
    >
    > }- Hide quoted text -
    >
    > - Show quoted text -


    Thank you.
     
    Saeed Amrollahi, Nov 6, 2009
    #5
  6. On Nov 4, 1:44 am, Saeed Amrollahi <> wrote:
    > Dear all
    >
    > I have a question. Is there any generic algorithm or solution to
    > access the keys or values of a map? I frequently face to such
    > problem and I usually write a function to copy the keys/values
    > of a map into a container let say a vector.
    >
    > Many thanks, in advance, for your help.


    What exactly do you want? You just want to access a map's current
    contents? Then iterate over the contents, like so:

    for (map<int, int>::iterator x = someMap.begin(); x != someMap.end(); +
    +x)
    {
    int const& key = x->first;
    int& value = x->second;
    //do whatever with this (key, value) pair
    }

    Do you want to create a new container which holds all of the keys? Or
    holds all of the values? Then iterate over the contents and build the
    new container, like so:

    map<int, int> someMap;
    vector<int> listOfKeys;
    for (map<int, int>::iterator x = someMap.begin(); x != someMap.end(); +
    +x)
    listOfKeys.push_back(x->first);

    I would not write a separate function for a two liner using very basic
    standard library stuff like this. Wrapping such basic usage for ease
    of use does not result in ease of use. It results in only obfuscation.
     
    Joshua Maurice, Nov 6, 2009
    #6
  7. Saeed Amrollahi

    gpderetta Guest

    On Nov 4, 1:05 pm, Alan Woodland <> wrote:
    >
    > There's a few annoying things about this though, the function take_first
    > has to live inside the anonymous namespace because it's not legal to
    > write the following, which given the absence of lambda functions would
    > be cleaner in my view:
    >
    > template <typename T1, typename T2>
    > std::list<T1> keys(const std::map<T1,T2>& in) {
    >    struct {
    >      const T1& operator()(const typename std::map<T1,T2>::value_type&
    > pair) {
    >        return pair.first;
    >      }
    >    } take_first;
    >
    >    std::list<T1> klist(in.size());
    >    std::transform(in.begin(), in.end(), klist.begin(), take_first);
    >    return klist;
    >
    > }
    >


    This will work:

    template <typename T1, typename T2>
    std::list<T1> keys(const std::map<T1,T2>& in) {
    struct take_first{
    static const T1& op(const typename std::map<T1,T2>::value_type&
    pair) {
    return pair.first;
    }
    };

    std::list<T1> klist(in.size());
    std::transform(in.begin(), in.end(), klist.begin(),
    &take_first::eek:p);
    return klist;
    }

    HTH,

    --
    gpd
     
    gpderetta, Nov 12, 2009
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. sks_cpp
    Replies:
    0
    Views:
    377
    sks_cpp
    Jul 26, 2003
  2. Erik Arner
    Replies:
    0
    Views:
    1,330
    Erik Arner
    Nov 2, 2004
  3. Marco Spatz

    Best wa to retrieve keys of a map

    Marco Spatz, May 8, 2006, in forum: C++
    Replies:
    3
    Views:
    393
    Selwyn Alcantara
    May 8, 2006
  4. Ram
    Replies:
    11
    Views:
    707
  5. alan
    Replies:
    3
    Views:
    380
    Victor Bazarov
    Nov 28, 2007
Loading...

Share This Page