迭代C++映射中的键

Bog*_*lan 109 c++ stl

有没有办法迭代键,而不是C++映射对?

aJ.*_*aJ. 110

map是关联容器.因此,迭代器是一对键,val.如果您只需要键,则可以忽略该对中的值部分.

for(std::map<Key,Val>::iterator iter = myMap.begin(); iter != myMap.end(); ++iter)
{
Key k =  iter->first;
//ignore value
//Value v = iter->second;
}
Run Code Online (Sandbox Code Playgroud)

编辑::如果您只想将键暴露给外部,那么您可以将地图转换为矢量或键并公开.

  • 有两件事,这回答了OP的问题,完全是他已经知道并且没有找到的答案,其次,如果你想做类似的事情,这个方法将无法帮助你:`std :: vector <Key> v(myMap.begin) (),myMap.end())`. (16认同)
  • 你可能想要这样做:`const Key&k(iter-> first);` (5认同)

Joh*_* H. 79

使用C++ 11,迭代语法很简单.你仍然迭代对,但只访问密钥很容易.

#include <iostream>
#include <map>

main()
{
    std::map<std::string, int> myMap;

    myMap["one"] = 1;
    myMap["two"] = 2;
    myMap["three"] = 3;

    for ( const auto &myPair : myMap ) {
        std::cout << myPair.first << "\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 最初的问题明确地说"不是对". (25认同)
  • 真的。但你需要以某种方式获取数据。我正在说明这样做的一个有用的习惯用法。 (5认同)

Ste*_*sop 70

如果你真的需要隐藏"真正的"迭代器返回的值(例如,因为你想要使用带有标准算法的键迭代器,以便它们对键而不是对键进行操作),那么看一下Boost的transform_iterator.

[提示:在查看新类的Boost文档时,请先阅读最后的"示例".然后你有一个运动的机会弄清楚其余部分在谈论什么:-)]

  • 使用boost,您可以编写BOOST_FOREACH(const key_t key,the_map | boost :: adapters :: map_keys){do something} http://www.boost.org/doc/libs/1_50_0/libs/range/doc/html/range /reference/adaptors/reference/map_keys.html (2认同)

Ian*_*Ian 38

没有提升

您可以通过简单地扩展该映射的STL迭代器来完成此操作.例如,字符串到int的映射:

#include <map>
typedef map<string, int> ScoreMap;
typedef ScoreMap::iterator ScoreMapIterator;

class key_iterator : public ScoreMapIterator
{
  public:
    key_iterator() : ScoreMapIterator() {};
    key_iterator(ScoreMapIterator s) : ScoreMapIterator(s) {};
    string* operator->() { return (string* const)&(ScoreMapIterator::operator->()->first); }
    string operator*() { return ScoreMapIterator::operator*().first; }
};
Run Code Online (Sandbox Code Playgroud)

您还可以在模板中执行此扩展,以获得更通用的解决方案.

你使用你的迭代器就像你使用列表迭代器一样,除了你迭代地图begin()end().

ScoreMap m;
m["jim"] = 1000;
m["sally"] = 2000;

for (key_iterator s = m.begin(); s != m.end(); ++s)
    printf("\n key %s", s->c_str());
Run Code Online (Sandbox Code Playgroud)

  • +1:最后,有人读了"不对"位!干杯,这节省了我挖掘规格的时间! (14认同)

Elm*_*mar 23

使用C++ 17,您可以在基于范围的for循环中使用结构化绑定(相应地调整John H.的答案):

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> myMap;

    myMap["one"] = 1;
    myMap["two"] = 2;
    myMap["three"] = 3;

    for ( const auto &[key, value]: myMap ) {
        std::cout << key << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,C++ 17标准要求你声明value变量,即使你没有使用它(std::ignore正如人们所使用的std::tie(..)那样不起作用,请参阅此讨论).

因此,某些编译器可能会警告您未使用的value变量!关于未使用变量的编译时警告对于我认为的任何生产代码都是不可行的.因此,这可能不适用于某些编译器版本.

  • 从 C++17 开始,您还可以使用 [[maybe_unused]]。这会抑制警告。像这样:`for ([[maybe_unused]] const auto &amp;[key, v_not_used] : my_map) { use(key); }` (2认同)

小智 17

使用 C++20,我们可以访问该ranges库,它对此有一个很好的解决方案:std::views::keys

#include <ranges>

//...

std::map<int, int> myMap = {{1,2},{3,4},{5,6}};
auto keys = std::views::keys(myMap);
for(auto key : keys) {
    std::cout << key << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

自己尝试一下: https: //godbolt.org/z/heeWv4Gh6


deg*_*ski 15

下面是Ian提到的更一般的模板化解决方案......

#include <map>

template<typename Key, typename Value>
using Map = std::map<Key, Value>;

template<typename Key, typename Value>
using MapIterator = typename Map<Key, Value>::iterator;

template<typename Key, typename Value>
class MapKeyIterator : public MapIterator<Key, Value> {

public:

    MapKeyIterator ( ) : MapIterator<Key, Value> ( ) { };
    MapKeyIterator ( MapIterator<Key, Value> it_ ) : MapIterator<Key, Value> ( it_ ) { };

    Key *operator -> ( ) { return ( Key * const ) &( MapIterator<Key, Value>::operator -> ( )->first ); }
    Key operator * ( ) { return MapIterator<Key, Value>::operator * ( ).first; }
};

template<typename Key, typename Value>
class MapValueIterator : public MapIterator<Key, Value> {

public:

    MapValueIterator ( ) : MapIterator<Key, Value> ( ) { };
    MapValueIterator ( MapIterator<Key, Value> it_ ) : MapIterator<Key, Value> ( it_ ) { };

    Value *operator -> ( ) { return ( Value * const ) &( MapIterator<Key, Value>::operator -> ( )->second ); }
    Value operator * ( ) { return MapIterator<Key, Value>::operator * ( ).second; }
};
Run Code Online (Sandbox Code Playgroud)

所有学分都归Ian ...谢谢Ian.


rod*_*gob 11

你正在寻找map_keys,你可以用它来写

BOOST_FOREACH(const key_t key, the_map | boost::adaptors::map_keys)
{
  // do something with key
}
Run Code Online (Sandbox Code Playgroud)


Nav*_*een 6

你想这样做吗?

std::map<type,type>::iterator iter = myMap.begin();
std::map<type,type>::iterator endIter = myMap.end();
for(; iter != endIter; ++iter)
{
   type key = iter->first;  
   .....
}
Run Code Online (Sandbox Code Playgroud)


Dar*_*ric 6

当不需要显式beginend时,即对于范围循环,可以通过以下方式获得键(第一个示例)或值(第二个示例)上的循环

#include <boost/range/adaptors.hpp>

map<Key, Value> m;

for (auto k : boost::adaptors::keys(m))
  cout << k << endl;

for (auto v : boost::adaptors::values(m))
  cout << v << endl;
Run Code Online (Sandbox Code Playgroud)

  • 应该在标准中 (2认同)

小智 6

没有BOOST,直接使用key和value

for(auto const& [key, value]: m_map)
    {
    std::cout<<" key="<<key;
    std::cout<<" value="<<value<<std::endl;
    }
Run Code Online (Sandbox Code Playgroud)

  • 这正是问题的作者所说的他们没有问的。 (2认同)

alg*_*gal 5

这是一个如何使用 Boost 的transform_iterator进行操作的示例

#include <iostream>
#include <map>
#include <iterator>
#include "boost/iterator/transform_iterator.hpp"

using std::map;
typedef std::string Key;
typedef std::string Val;

map<Key,Val>::key_type get_key(map<Key,Val>::value_type aPair) {
  return aPair.first;
}

typedef map<Key,Val>::key_type (*get_key_t)(map<Key,Val>::value_type);
typedef map<Key,Val>::iterator map_iterator;
typedef boost::transform_iterator<get_key_t, map_iterator> mapkey_iterator;

int main() {
  map<Key,Val> m;
  m["a"]="A";
  m["b"]="B";
  m["c"]="C";

  // iterate over the map's (key,val) pairs as usual
  for(map_iterator i = m.begin(); i != m.end(); i++) {
    std::cout << i->first << " " << i->second << std::endl;
  }

  // iterate over the keys using the transformed iterators
  mapkey_iterator keybegin(m.begin(), get_key);
  mapkey_iterator keyend(m.end(), get_key);
  for(mapkey_iterator i = keybegin; i != keyend; i++) {
    std::cout << *i << std::endl;
  }
}
Run Code Online (Sandbox Code Playgroud)