从地图获取值列表

发布于 2024-10-02 22:48:41 字数 189 浏览 1 评论 0原文

有没有一种stl方法可以从地图中获取值列表?

即,我有:

std::map<A,B> myMap;

并且我想要一个仅返回值列表的函数,即 std::list (或为此设置。 有内置的 stl 方法可以做到这一点吗?

Is there an stl way to get a list of values from a map?

i.e, I have:

std::map<A,B> myMap;

and I would like a function that will return just the list of values, i.e, std::list<B> (or set for that matter.
Is there a built-in stl way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

娇纵 2024-10-09 22:48:41

map元素被定义为map::value_type,其类型为pairfirst 是键,second 是值。您可以编写一个函子来从value_type中提取第二个,并将其复制到向量(或列表,或任何你想要的。)进行复制的最佳方法是使用变换,正如其名称所暗示的那样:它接受一种类型的值并将其转换为另一种类型的值。

这是一个完整的工作示例:

#include <cstdlib>
#include <map>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

typedef map<unsigned, string> MyMap;
MyMap my_map;

struct get_second : public std::unary_function<MyMap::value_type, string>
{
    string operator()(const MyMap::value_type& value) const
    {
        return value.second;
    }
};

int main()
{
    my_map[1] = "one";
    my_map[2] = "two";
    my_map[3] = "three";
    my_map[4] = "four";
    my_map[5] = "five";

    // get a vector of values
    vector<string> my_vals;
    transform(my_map.begin(), my_map.end(), back_inserter(my_vals), get_second() );

    // dump the list
    copy( my_vals.begin(), my_vals.end(), ostream_iterator<string>(cout, "\n"));
}

编辑:

如果您有支持 C++0x 的编译器lambdas,你可以完全消除函子。这对于使代码更具可读性、可论证性、更易于维护非常有用,因为您最终不会在代码库中出现数十个小的一次性函子。以下是如何更改上面的代码以使用 lambda:

transform(my_map.begin(), my_map.end(), back_inserter(my_vals), [](const MyMap::value_type& val){return val.second;} );

A map element is defined as a map::value_type, and the type of it is a pair<A,B>. first is the key and second is the value. You can write a functor to extract second from a value_type, and copy that in to a vector (or a list, or whatever you want.) The best way to do the copying is to use transform, which does just what its name implies: it takes a value of one type and transforms it to a different type of value.

Here's a complete working example:

#include <cstdlib>
#include <map>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;

typedef map<unsigned, string> MyMap;
MyMap my_map;

struct get_second : public std::unary_function<MyMap::value_type, string>
{
    string operator()(const MyMap::value_type& value) const
    {
        return value.second;
    }
};

int main()
{
    my_map[1] = "one";
    my_map[2] = "two";
    my_map[3] = "three";
    my_map[4] = "four";
    my_map[5] = "five";

    // get a vector of values
    vector<string> my_vals;
    transform(my_map.begin(), my_map.end(), back_inserter(my_vals), get_second() );

    // dump the list
    copy( my_vals.begin(), my_vals.end(), ostream_iterator<string>(cout, "\n"));
}

EDIT:

If you have a compiler that supports C++0x lambdas, you can eliminate the functor entirely. This is very useful for making code more readable and, arguable, easier to maintain since you don't end up with dozens of little one-off functors floating around in your codebase. Here's how you would change the code above to use a lambda:

transform(my_map.begin(), my_map.end(), back_inserter(my_vals), [](const MyMap::value_type& val){return val.second;} );
烟沫凡尘 2024-10-09 22:48:41

没有内置任何东西,没有。不过,编写自己的函数非常简单:迭代地图。迭代器将为您提供一个pair。将每个第二值添加到结果列表中。

There's nothing built in, no. It's simple enough to write your own function, though: Iterate over the map. The iterator will give you a pair<A, B>. Add each second value to the result list.

山川志 2024-10-09 22:48:41

你不能只是“获取”这样一个列表,因为内部任何地方都没有存储任何预先存在的列表,但你可以构建一个:

typedef std::map<A,B> myMapType;
myMapType myMap;
std::list<B> valueList;
for (myMapType::const_iterator it=myMap.begin(); it!=myMap.end(); ++it) {
  valueList.push_back( it->second );
}

或者如果你真的喜欢更 STL 的方式:

class GetSecond {
  template<typename T1, typename T2>
  const T2& operator()( const std::pair<T1,T2>& key_val ) const
    { return key_val.second; }
};

typedef std::map<A,B> myMapType;
myMapType myMap;
std::list<B> valueList;
std::transform(myMap.begin(), myMap.end(), std::back_inserter(valueList),
               GetSecond());

You can't just "get" such a list because there is no pre-existing list stored anywhere in the guts, but you can build one:

typedef std::map<A,B> myMapType;
myMapType myMap;
std::list<B> valueList;
for (myMapType::const_iterator it=myMap.begin(); it!=myMap.end(); ++it) {
  valueList.push_back( it->second );
}

Or if you really like the more STL way:

class GetSecond {
  template<typename T1, typename T2>
  const T2& operator()( const std::pair<T1,T2>& key_val ) const
    { return key_val.second; }
};

typedef std::map<A,B> myMapType;
myMapType myMap;
std::list<B> valueList;
std::transform(myMap.begin(), myMap.end(), std::back_inserter(valueList),
               GetSecond());
×眷恋的温暖 2024-10-09 22:48:41

许多“内置”方法之一当然是最明显的一种。只需迭代所有按键 (pair::first) 排序的pair 元素,并将值 (pair::second) 添加到新容器中,您可以在可以使用正确的容量进行构造,以在迭代和添加过程中消除多余的分配。

请注意:std::list 很少是您真正想要使用的容器。当然,除非您真的非常确实需要它的特定功能。

One of many "built-in" ways is of course the most obvious one. Just iterate over all pair elements, which are ordered by key (pair::first), and add the value (pair::second) to a new container, which you can construct with the correct capacity to get rid of excess allocations during the iteration and adding.

Just a note: std::list is seldom the container you actually want to be using. Unless, of course, you really, really do need its specific features.

煮酒 2024-10-09 22:48:41

当然。

std::list<B> list;
std::for_each(myMap.begin(), myMap.end(), [&](const std::pair<const A, B>& ref) {
    list.push_back(ref.second);
});

如果您没有 C++0x 编译器,首先我对您表示同情,其次您需要为此目的构建一个快速函数对象。

Sure.

std::list<B> list;
std::for_each(myMap.begin(), myMap.end(), [&](const std::pair<const A, B>& ref) {
    list.push_back(ref.second);
});

If you don't have a C++0x compiler, first you have my sympathies, and second, you will need to build a quick function object for this purpose.

烟雨凡馨 2024-10-09 22:48:41

您可以使用boost的transform_iteratorhttp://www.boost.org/doc/libs/1_64_0/libs/iterator/doc/transform_iterator.html

struct GetSecond {
  template <typename K, typename T>
  const T& operator()(const std::pair<K, T> & p) const { return p.second; }
  template <typename K, typename T>
  T& operator()(std::pair<K, T> & p) const { return p.second; }
};

template <typename MapType>
  auto begin_values(MapType& m) -> decltype(boost::make_transform_iterator(m.begin(), GetSecond())) {
  return boost::make_transform_iterator(m.begin(), GetSecond());
}

template <typename MapType>
  auto end_values(MapType& m) -> decltype(boost::make_transform_iterator(m.end(), GetSecond())) {
  return boost::make_transform_iterator(m.end(), GetSecond());
}

template <typename MapType>
  struct MapValues {
  MapType & m;
  MapValues(MapType & m) : m(m) {}
  typedef decltype(begin_values(m)) iterator;
  iterator begin() { return begin_values(m); }
  iterator end() { return end_values(m); }
};

template <typename MapType>
  MapValues<MapType> get_values(MapType & m) {
  return MapValues<MapType>(m);
}


int main() {
  std::map<int, double> m;
  m[0] = 1.0;
  m[10] = 2.0;
  for (auto& x : get_values(m)) {
    std::cout << x << ',';
    x += 1;
  }
  std::cout << std::endl;
  const std::map<int, double> mm = m;
  for (auto& x : get_values(mm)) {
    std::cout << x << ',';
  }
  std::cout << std::endl;
}

You can use boost's transform_iterator: http://www.boost.org/doc/libs/1_64_0/libs/iterator/doc/transform_iterator.html

struct GetSecond {
  template <typename K, typename T>
  const T& operator()(const std::pair<K, T> & p) const { return p.second; }
  template <typename K, typename T>
  T& operator()(std::pair<K, T> & p) const { return p.second; }
};

template <typename MapType>
  auto begin_values(MapType& m) -> decltype(boost::make_transform_iterator(m.begin(), GetSecond())) {
  return boost::make_transform_iterator(m.begin(), GetSecond());
}

template <typename MapType>
  auto end_values(MapType& m) -> decltype(boost::make_transform_iterator(m.end(), GetSecond())) {
  return boost::make_transform_iterator(m.end(), GetSecond());
}

template <typename MapType>
  struct MapValues {
  MapType & m;
  MapValues(MapType & m) : m(m) {}
  typedef decltype(begin_values(m)) iterator;
  iterator begin() { return begin_values(m); }
  iterator end() { return end_values(m); }
};

template <typename MapType>
  MapValues<MapType> get_values(MapType & m) {
  return MapValues<MapType>(m);
}


int main() {
  std::map<int, double> m;
  m[0] = 1.0;
  m[10] = 2.0;
  for (auto& x : get_values(m)) {
    std::cout << x << ',';
    x += 1;
  }
  std::cout << std::endl;
  const std::map<int, double> mm = m;
  for (auto& x : get_values(mm)) {
    std::cout << x << ',';
  }
  std::cout << std::endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文