To retrieve Keys or values of a Map

  • Thread starter Saeed Amrollahi
  • Start date
S

Saeed Amrollahi

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.
 
A

Alan Woodland

Saeed said:
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
 
S

Saeed Amrollahi

Saeed said:
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
 
M

mzdude

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;
}
 
S

Saeed Amrollahi

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.
 
J

Joshua Maurice

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.
 
G

gpderetta

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,
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top