使用std::矢量进行std::map初始化

std::map initialization with a std::vector

本文关键字:std map 初始化 使用      更新时间:2023-10-16

我想用std::vector对象中包含的键初始化std::map对象。

std::vector<char> mykeys { 'a', 'b', 'c' ];
std::map<char, int> myMap;

如果没有循环,我怎么能做到这一点?

我可以为我的int添加一个默认值吗?

没有显式循环:

std::transform( std::begin(mykeys), std::end(mykeys),
                std::inserter(myMap, myMap.end()),
                [] (char c) {return std::make_pair(c, 0);} );

演示

不过,基于范围的循环会更性感,所以如果可能的话,请使用它:

for (auto c : mykeys)
    myMap.emplace(c, 0);

,如果没有循环或等效构造,就无法做到这一点。(句号)您可以将循环隐藏在某些函数中,如std::transform(),但不能避免。此外,编译器经过良好的训练可以优化循环(因为它们是三引号的),因此没有充分的理由避免它们。

如果没有循环,就无法做到这一点。您可以做的是在标准算法下隐藏循环,因为您需要将char类型的对象转换为std::map<char, int>::value_type类型的对象,该对象表示自己std::pair<const char, int>

例如

#include <iostream>
#include <vector>
#include <map>
#include <iterator>
#include <algorithm>
int main() 
{
    std::vector<char> v { 'a', 'b', 'c' };
    std::map<char, int> m;
    std::transform( v.begin(), v.end(), std::inserter( m, m.begin() ),
        []( char c ){ return std::pair<const char, int>( c, 0 ); } );
    for ( const auto &p : m )
    {
        std::cout << p.first << 't' << p.second << std::endl;
    }
    return 0;
}

输出为

a   0
b   0
c   0

使用boost:

template<class Iterators, class Transform>
boost::iterator_range< boost::transform_iterator<
  typename std::decay_t<Transform>::type,
  Iterator
>> make_transform_range( Iterator begin, Iterator end, Transform&& t ) {
  return {
    boost::make_transform_iterator( begin, t ),
    boost::make_transform_iterator( end, t )
  };
}

将密钥映射到对的助手:

template<class T>
struct key_to_element_t {
  T val;
  template<class K>
  std::pair< typename std::decay<K>::type, T > operator()(K&& k) const {
    return std::make_pair( std::forward<K>(k), val );
  }
};
template<class T>
key_to_element_t< typename std::decay<T>::type > key_to_element( T&& t ) {
  return { std::forward<T>(t) };
}
template<class R>
struct range_to_container_t {
  R r;
  template<class C>
  operator C()&& {
    using std::begin; using std::end;
    return { begin(std::forward<R>(r)), end(std::forward<R>(r)) };
  }
};
template<class R>
range_to_container_t<R> range_to_container( R&& r ) { return std::forward<R>(r); }

在经历了这么多混乱之后:

std::vector<char> mykeys { 'a', 'b', 'c' ];
std::map<char, int> myMap = range_to_container( make_transform_range( begin(mykeys), end(mykeys), key_to_element( 0 ) ) );

其直接从CCD_ 10载体中的元素的变换序列构建CCD_。

真傻。