首页 文章

如何从std :: map中检索所有键(或值)并将它们放入向量中?

提问于
浏览
185

这是我出来的可能方式之一:

struct RetrieveKey
{
    template <typename T>
    typename T::first_type operator()(T keyValuePair) const
    {
        return keyValuePair.first;
    }
};

map<int, int> m;
vector<int> keys;

// Retrieve all keys
transform(m.begin(), m.end(), back_inserter(keys), RetrieveKey());

// Dump all keys
copy(keys.begin(), keys.end(), ostream_iterator<int>(cout, "\n"));

当然,我们也可以通过定义另一个仿函数 RetrieveValues 来从 Map 中检索所有值 .

有没有其他方法可以轻松实现这一目标? (我总是想知道为什么std :: map不包含我们这样做的成员函数 . )

14 回答

  • 10

    虽然您的解决方案应该可行,但根据您的程序员的技能水平,可能难以阅读 . 此外,它还将功能从呼叫站点移开 . 这可能会使维护变得更加困难 .

    我不确定你的目标是将密钥插入到矢量中还是将它们打印到cout所以我正在做两件事 . 你可以尝试这样的事情:

    map<int, int> m;
    vector<int> v;
    for(map<int,int>::iterator it = m.begin(); it != m.end(); ++it) {
      v.push_back(it->first);
      cout << it->first << "\n";
    }
    

    或者更简单,如果你使用Boost:

    map<int,int> m;
    pair<int,int> me; // what a map<int, int> is made of
    vector<int> v;
    BOOST_FOREACH(me, m) {
      v.push_back(me.first);
      cout << me.first << "\n";
    }
    

    就个人而言,我喜欢BOOST_FOREACH版本,因为键入的内容较少,而且它的内容非常明确 .

  • 9
    //c++0x too
    std::map<int,int> mapints;
    std::vector<int> vints;
    vints.reserve(mapints.size());
    for(auto const& imap: mapints)
        vints.push_back(imap.first);
    
  • 9

    为此目的有一个boost range adaptor

    vector<int> keys;
    // Retrieve all keys
    boost::copy(m | boost::adaptors::map_keys, std::back_inserter(keys));
    

    有一个类似的map_values范围适配器用于提取值 .

  • 39

    C 0x给了我们一个更好的解决方案:

    std::vector<int> keys;
    
    std::transform(
        m_Inputs.begin(),
        m_Inputs.end(),
        std::back_inserter(keys),
        [](const std::map<int,int>::value_type &pair){return pair.first;});
    
  • 4

    SGI STL有一个名为select1st的扩展名 . 太糟糕了,它不是标准的STL!

  • 4

    我认为上面提到的BOOST_FOREACH很好而且干净,但是,还有另一个使用BOOST的选项 .

    #include <boost/lambda/lambda.hpp>
    #include <boost/lambda/bind.hpp>
    
    std::map<int, int> m;
    std::vector<int> keys;
    
    using namespace boost::lambda;
    
    transform(      m.begin(), 
                    m.end(), 
                    back_inserter(keys), 
                    bind( &std::map<int,int>::value_type::first, _1 ) 
              );
    
    copy( keys.begin(), keys.end(), std::ostream_iterator<int>(std::cout, "\n") );
    

    就个人而言,我不认为这种方法在这种情况下与BOOST_FOREACH方法一样干净,但在其他情况下,boost :: lambda可能非常干净 .

  • -3

    @ DanDan的答案,使用C 11是:

    using namespace std;
    vector<int> keys;
    
    transform(begin(map_in), end(map_in), back_inserter(keys), 
                [](decltype(map_in)::value_type const& pair) {
        return pair.first;
    });
    

    并使用C 14(如@ ivan.ukr所述)我们可以用 auto 替换 decltype(map_in)::value_type .

  • 127

    您的解决方案很好,但您可以使用迭代器来执行此操作:

    std::map<int, int> m;
    m.insert(std::pair<int, int>(3, 4));
    m.insert(std::pair<int, int>(5, 6));
    for(std::map<int, int>::const_iterator it = m.begin(); it != m.end(); it++)
    {
        int key = it->first;
        int value = it->second;
        //Do something
    }
    
  • 55

    此外,如果您有Boost,请使用transform_iterator以避免生成密钥的临时副本 .

  • 7

    您可以使用通用的boost :: transform_iterator . transform_iterator允许您转换迭代值,例如在您只想处理键而不是值时 . 见http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/transform_iterator.html#example

  • 1

    最好的非sgi,非boost STL解决方案是扩展map :: iterator,如下所示:

    template<class map_type>
    class key_iterator : public map_type::iterator
    {
    public:
        typedef typename map_type::iterator map_iterator;
        typedef typename map_iterator::value_type::first_type key_type;
    
        key_iterator(const map_iterator& other) : map_type::iterator(other) {} ;
    
        key_type& operator *()
        {
            return map_type::iterator::operator*().first;
        }
    };
    
    // helpers to create iterators easier:
    template<class map_type>
    key_iterator<map_type> key_begin(map_type& m)
    {
        return key_iterator<map_type>(m.begin());
    }
    template<class map_type>
    key_iterator<map_type> key_end(map_type& m)
    {
        return key_iterator<map_type>(m.end());
    }
    

    然后像这样使用它们:

    map<string,int> test;
            test["one"] = 1;
            test["two"] = 2;
    
            vector<string> keys;
    
    //      // method one
    //      key_iterator<map<string,int> > kb(test.begin());
    //      key_iterator<map<string,int> > ke(test.end());
    //      keys.insert(keys.begin(), kb, ke);
    
    //      // method two
    //      keys.insert(keys.begin(),
    //           key_iterator<map<string,int> >(test.begin()),
    //           key_iterator<map<string,int> >(test.end()));
    
            // method three (with helpers)
            keys.insert(keys.begin(), key_begin(test), key_end(test));
    
            string one = keys[0];
    
  • 4

    c 11的一点是:

    std::map<uint32_t, uint32_t> items;
    std::vector<uint32_t> itemKeys;
    for (auto & kvp : items)
    {
        itemKeys.emplace_back(kvp.first);
        std::cout << kvp.first << std::endl;
    }
    
  • 139

    这是一个很好的使用C 11魔术的函数模板,适用于std :: map,std :: unordered_map:

    template<template <typename...> class MAP, class KEY, class VALUE>
    std::vector<KEY>
    keys(const MAP<KEY, VALUE>& map)
    {
        std::vector<KEY> result;
        result.reserve(map.size());
        for(const auto& it : map){
            result.emplace_back(it.first);
        }
        return result;
    }
    

    在这里查看:http://ideone.com/lYBzpL

  • 5

    (我总是想知道为什么std :: map不包含我们这样做的成员函数 . )

    因为它无法做到比你做得更好 . 如果一个方法的实现不会优于自由函数的实现,那么通常你不应该编写一个方法;你应该写一个免费的功能 .

    目前还不清楚为什么它仍然有用 .

相关问题