C++ 是否可以将STL复制功能与map一起使用

C++ 是否可以将STL复制功能与map一起使用,c++,stl,map,copy,C++,Stl,Map,Copy,我想知道是否有什么技巧可以使用copy with maps将map的内容复制到数组中。因为STL映射是由键值和映射值组合而成的,所以映射的元素形成键值对。这使我们无法使用标准算法,如std::copy。例如,以下代码给出了错误: #include <iostream> #include <algorithm> #include <vector> #include <map> int main() { std::map <int, dou

我想知道是否有什么技巧可以使用copy with maps将map的内容复制到数组中。因为STL映射是由键值和映射值组合而成的,所以映射的元素形成键值对。这使我们无法使用标准算法,如std::copy。例如,以下代码给出了错误:

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

int
main()
{
  std::map <int, double> test(4);
  test[0] = 11;
  test[2] = 1.23;
  test[3] = 23.29;
  test[1] = 12.12;
  double *test_arr = (double *) malloc(4 * sizeof(double));
  std::copy(test.begin(), test.end(), test_arr);
  std::cout << test_arr[3] << std::endl;
  return 0;
}
#包括
#包括
#包括
#包括
int
main()
{
标准:map试验(4);
试验[0]=11;
试验[2]=1.23;
试验[3]=23.29;
试验[1]=12.12;
double*test_arr=(double*)malloc(4*sizeof(double));
复制(test.begin(),test.end(),test\u arr);
std::cout您的目标将是一个数组
std::vector
[请!]的
std::pair
对象,除非您自己展开它


(你可以创建你自己的
inputierator
作为代理,或者玩
std::transform
std::back\u插入器,但那太傻了。你会让你的代码比在映射中循环更冗长。)

你可以使用
std::transform

template <typename T, typename U>
const U &extract_second(const std::pair<T,U> &p)
{
    return p.second;
}

std::transform(test.begin(), test.end(), test_arr, extract_second<int,double>);
模板
常量U和提取_秒(常量标准::对和对)
{
返回p.second;
}
std::transform(test.begin()、test.end()、test\u arr、extract\u second);
正如@Andre在下面的一条评论中指出的,如果您想要更详细的开销,可以避免通过函子显式声明模板参数:

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

std::transform(test.begin(), test.end(), test_arr, extract_second());
struct extract\u秒
{
模板
常量U运算符()(常量std::pair&p)常量
{
返回p.second;
}
};
转换(test.begin(),test.end(),test_arr,extract_second());

我确信有一种使用Boost binders的不太详细的解决方案,但我记不清语法了。

EWW,malloc?无论如何,如果你想复制地图,你也必须记住关键点

int main()
{
    std::map <int, double> test(4);
    test[0] = 11;
    test[2] = 1.23;
    test[3] = 23.29;
    test[1] = 12.12;
    std::vector<std::pair<int, double>> test_arr(test.size());
    std::copy(test.begin(), test.end(), test_arr.begin());
    std::cout << test_arr[3] << std::endl;
    return 0;
}
intmain()
{
标准:map试验(4);
试验[0]=11;
试验[2]=1.23;
试验[3]=23.29;
试验[1]=12.12;
std::向量测试(test.size());
复制(test.begin(),test.end(),test_arr.begin());
STD::CUT

如果您考虑<代码> STD::MAP<代码> STL容器,那么它是一个容器

std::pair
(这就是它的
值类型
) 定义为,并且设计为可以用作 如果您只需要它的一部分,那么正确的函数是
std::transform
,带有映射
值\u类型
键\u类型
映射的\u类型
(如果您选择 大量使用
std::pair
-或
std::map
,其
value\u type
std::pair
,您应该在 您的工具包:

struct ExtractFirst
{
    template<typename Pair>
    typename boost::remove_const<typename Pair::first_type>::type
                        operator()( Pair const& from ) const
    {
        return from.first;
    }
};
struct-ExtractFirst
{
模板
typename boost::remove_const::type
运算符()
{
从第一位返回;
}
};

,对于
ExtractSecond

来说,同样的事情最简单的方法是与以下组合使用:


在你的免责声明中:那么你认为
std::copy
做什么呢?@Xeo:他的意思是他不想在他的代码中写出循环。高度相关:或者如果你想要一个双精度数组,而不想写循环,你可以改为编写一个输出迭代器,用
操作符=(const pair&p){*(此->基础的_ptr)=p.second;}
。Boost迭代器助手中可能有这样做的东西,我还没有看。@Steve:是的,你可以将逻辑应用到
输出迭代器上,就像应用到
输入迭代器上一样容易。现在你提到它,可能更容易了。我喜欢将
提取秒
写成:
结构提取秒{template const U&operator()(const std::pair&p){return p.second;}const};
以便可以在调用中省略模板参数:
std::transform(test.begin(),test.end(),test_arr,extract_second())
@Andre:谢谢!我已经将你的版本集成到我的答案中了。多亏了奥利,我忘了使用std::transform,詹姆斯还指出了从映射中提取值的boost方法。@systemsfault:没问题。请注意,@James'的解决方案实际上与我的相当;我认为有一个使用
boost::bind
的解决方案可以避免这种情况要显式地编写函子。
struct ExtractFirst
{
    template<typename Pair>
    typename boost::remove_const<typename Pair::first_type>::type
                        operator()( Pair const& from ) const
    {
        return from.first;
    }
};
typedef std::map<int, double> map_t;
map_t mm;

// add elements to mm
// ...

// copy
typedef std::vector<double> vec_t;
vec_t vv;
vv.reserve( mm.size() );
std::transform( mm.begin(), mm.end(), std::back_inserter(vv), 
  boost::bind( &map_t::value_type::second, _1 ) );
std::transform( mm.begin(), mm.end(), back_inserter(vv), 
  [](map_t::value_type val) -> double { return val.second; } );
// or
std::for_each( mm.begin(), mm.end(), 
  [&vv](map_t::value_type val) { vv.push_back( val.second ); } );