303

これは私が出てくる可能な方法の1つです:

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を定義することで、マップからすべての値を取得することもできます。

これを簡単に達成する他の方法はありますか?(なぜ std::map にメンバー関数が含まれていないのか、いつも疑問に思っています。)

4

22 に答える 22

205

ソリューションは機能するはずですが、仲間のプログラマーのスキル レベルによっては読みにくい場合があります。さらに、機能を呼び出しサイトから移動します。これにより、メンテナンスが少し難しくなる可能性があります。

あなたの目標がキーをベクトルに入れることなのか、それらを印刷して出力することなのかはわかりません。両方をやっています。次のようなことを試すことができます:

std::map<int, int> m;
std::vector<int> key, value;
for(std::map<int,int>::iterator it = m.begin(); it != m.end(); ++it) {
  key.push_back(it->first);
  value.push_back(it->second);
  std::cout << "Key: " << it->first << std::endl();
  std::cout << "Value: " << it->second << std::endl();
}

または、ブーストを使用している場合はさらに簡単です。

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 バージョンが好きです。タイピングが少なく、何をしているのかが非常に明確だからです。

于 2008-09-21T04:38:34.450 に答える
186
//c++0x too
std::map<int,int> mapints;
std::vector<int> vints;
for(auto const& imap: mapints)
    vints.push_back(imap.first);
于 2012-03-13T22:33:32.230 に答える
67

この目的のためのブースト範囲アダプターがあります。

#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/copy.hpp>
vector<int> keys;
boost::copy(m | boost::adaptors::map_keys, std::back_inserter(keys));

値を抽出するための同様の map_values 範囲アダプターがあります。

于 2012-03-05T19:29:46.923 に答える
54

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;});
于 2010-05-08T13:07:44.007 に答える
22

C++ 11を使用した@DanDanの答えは次のとおりです。

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 によって指摘されているように)、 に置き換えることができdecltype(map_in)::value_typeますauto

于 2016-09-16T12:47:48.270 に答える
14

あなたのソリューションは問題ありませんが、イテレータを使用してそれを行うことができます:

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
}
于 2008-09-21T03:57:37.183 に答える
12

SGI STL には、 という拡張子がありselect1stます。残念ながら、標準の STL ではありません。

于 2008-09-21T03:31:46.543 に答える
9

上記の 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 は他の場合では本当にクリーンになる可能性があります。

于 2008-09-21T06:24:03.620 に答える
7

また、Boost がある場合は、transform_iterator を使用して、キーの一時的なコピーを作成しないようにします。

于 2008-09-21T04:05:36.230 に答える
6

多目的な boost::transform_iterator を使用できます。transform_iterator を使用すると、反復値を変換できます。たとえば、値ではなくキーのみを処理する場合です。http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/transform_iterator.html#exampleを参照してください。

于 2008-09-21T04:14:42.167 に答える
6

C++17構造化バインディング (「destructuring」) 宣言構文では、

これを行うと、理解しやすくなります。

// To get the keys
std::map<int, double> map;
std::vector<int> keys;
keys.reserve(map.size());
for(const auto& [key, value] : map) {
    keys.push_back(key);
}
// To get the values
std::map<int, double> map;
std::vector<double> values;
values.reserve(map.size());
for(const auto& [key, value] : map) {
    values.push_back(value);
}
于 2021-01-27T12:12:47.987 に答える
4

最適な非 SGI、非ブースト 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];
于 2010-03-05T19:15:20.503 に答える
0

アトミックマップの例

#include <iostream>
#include <map>
#include <vector> 
#include <atomic>

using namespace std;

typedef std::atomic<std::uint32_t> atomic_uint32_t;
typedef std::map<int, atomic_uint32_t> atomic_map_t;

int main()
{
    atomic_map_t m;

    m[4] = 456;
    m[2] = 45678;

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

    return 0;
}
于 2020-03-24T19:39:08.490 に答える
-4

(なぜstd :: mapにメンバー関数が含まれていないのか疑問に思っています。)

それはあなたがそれをすることができるよりそれをより良くすることができないからです。メソッドの実装がfree関数の実装より優れていない場合は、一般にメソッドを作成しないでください。無料の関数を書く必要があります。

とにかくなぜそれが有用なのかもすぐには明らかではありません。

于 2008-09-21T11:13:15.170 に答える