Iterate Keys in a C++ Map

Iterate keys in a C++ map

If you really need to hide the value that the "real" iterator returns (for example because you want to use your key-iterator with standard algorithms, so that they operate on the keys instead of the pairs), then take a look at Boost's transform_iterator.

[Tip: when looking at Boost documentation for a new class, read the "examples" at the end first. You then have a sporting chance of figuring out what on earth the rest of it is talking about :-)]

How to iterate over a C++ STL map data structure using the 'auto' keyword?

This code uses 2 new features from C++11 standard the auto keyword, for type inference, and the range based for loop.

Using just auto this can be written as (thanks Ben)

for (auto it=mymap.begin(); it!=mymap.end(); ++it)

Using just range for this can be written as

for (std::pair<const char,int>& x: mymap) {
std::cout << x.first << " => " << x.second << '\n';
}

Both of these do the exact same task as your two versions.

How can I loop through a C++ map of maps?

Old question but the remaining answers are outdated as of C++11 - you can use a ranged based for loop and simply do:

std::map<std::string, std::map<std::string, std::string>> mymap;

for(auto const &ent1 : mymap) {
// ent1.first is the first key
for(auto const &ent2 : ent1.second) {
// ent2.first is the second key
// ent2.second is the data
}
}

this should be much cleaner than the earlier versions, and avoids unnecessary copies.

Some favour replacing the comments with explicit definitions of reference variables (which get optimised away if unused):

for(auto const &ent1 : mymap) {
auto const &outer_key = ent1.first;
auto const &inner_map = ent1.second;
for(auto const &ent2 : inner_map) {
auto const &inner_key = ent2.first;
auto const &inner_value = ent2.second;
}
}

Iterating over keys/values of a std::map in C++

Try this:

template <typename Iter>
struct KeyGetter : std::unary_function<typename Iter::value_type,
typename Iter::value_type::first_type>
{
const typename Iter::value_type::first_type& operator()
(const typename Iter::value_type& p) const
{ return p.first; }
};

template<typename Iter>
boost::transform_iterator<KeyGetter<Iter>, Iter> key_iterator(Iter itr)
{
return boost::make_transform_iterator<KeyGetter<Iter>, Iter>
(itr, KeyGetter<Iter>());
}

The idea being that the function at the call site should be templated directly on its argument, to avoid having to specify the template arguments explicitly.

How to iterate over a nested map in c:forEach

Each iteration of Map in a c:forEach gives a Map.Entry instance which in turn has getKey() and getValue() methods. It's similar to doing for (Entry entry : map.entrySet()) in plain Java.

E.g.

<c:forEach items="#{bean.map}" var="entry">
<h:outputText value="Key: #{entry.key}, Value: #{entry.value}" /><br />
</c:forEach>

In case of a Map<Integer, Map<String, String[]>> the #{entry.value} returns a Map<String, String[]>, so you need to iterate over it as well:

<c:forEach items="#{bean.map}" var="entry">
<h:outputText value="Key: #{entry.key}, Values:" />
<c:forEach items="#{entry.value}" var="nestedentry">
<h:outputText value="Nested Key: #{nestedentry.key}, Nested Value: #{nestedentry.value}" />
</c:forEach><br />
</c:forEach>

But in your case, the #{nestedentry.value} is actually a String[], so we need to iterate over it again:

<c:forEach items="#{bean.map}" var="entry">
<h:outputText value="Key: #{entry.key}, Values:" />
<c:forEach items="#{entry.value}" var="nestedentry">
<h:outputText value="Nested Key: #{nestedentry.key}, Nested Values: " />
<c:forEach items="#{nestedentry.value}" var="nestednestedentry">
<h:outputText value="#{nestednestedentry}" />
</c:forEach><br />
</c:forEach><br />
</c:forEach>

By the way, this ought to work with rich:dataList as well.

How do you iterate through a C++ map?

for( auto const& pair : family )
{
cout << pair.first << " represented by object at " << (void*)pair.second << "\n";
}

Instead of using a loop to delete objects, consider storing the objects directly instead of pointers to dynamically allocated objects.

Here's one way to delete all Person objects and remove their map entries:

while( not family.empty() )
{
auto const it = family.begin();
delete it->first;
family.erase( it );
}

If instead you store Person objects (not pointers to dynamically allocated objects) this reduces to

family.clear();

Iterating through map keys in C++ 17

Two options:

  1. A ranged-for version of @πάνταῥεῖ 's answer:

    for (auto const& pair : myMap) {
    auto key = pair.first;
    // etc. etc.
    }
  2. Use the ranges-v3 library (or std::ranges in C++20) to adapt the range myMap.begin() and myMap.end() by projecting it onto its first coordinate. Then you'd write something like:

    for (auto key : keys_of(myMap) ) {
    // etc. etc.
    }

    you can do this without ranges if keys_of() materializes all of the keys, but that could be expensive for a larger map.

    (If you have weird, heavy keys, then const auto& key instead of auto key.)

Iterate through a Map by key

to iterate over a map you need to keep a Collection instance.
Therefore change your map as below:

public HashMap<String, List<ProtocolNode>> getPendingNodes()
{
return this.pending_nodes;
}

or to fix your own code use below method:

Map<String, ProtocolNode> testMap = new HashMap<String, ProtocolNode>();

for( Entry<String, ProtocolNode> entry : testMap.entrySet() ){
if( entry.getKey().equals( "MYKEY" ) ){
System.out.println( entry.getValue() );
}
}

You have to use entryset, there's no other way.

Get map from map by vector of keys

I know I could iterate over the vector, but this doesn't make much of a difference, or does it?

It does make a difference, because iterating in order is typically faster for a vector than for a map (vectors data is local in memory, a maps elements are not) and finding an element is faster in a map than in a vector (O(log(N)) vs O(N) for an unsorted vector).

Lets say you have M elements in the map and N keys in the vector, then your approach is O( M * N) while swapping iteration and finding would be only O( N * log(M)). This only takes into account the complexity for find. Taking into account the iteration is more involved as it very much depends on cache.

Otherwise, I think your approach is fine. I am not aware of an algorithm that would make your code more concise or expressive.

PS you might consider this as a nitpick on wording, but as it happens too often that one overthinks a problem I will mention it: "a smarter way" is not always "a better way". Dont try to be too smart. Most algorithms can be replaced by a simple loop, but often they are considered more expressive and readable than the handwritten loop. Trying to squeeze something into algorithms when there is no algorithm for the problem at hand, often results in less readable and less expressive code. If someone finds an algorithm that can be used here, I'll take back everything in this PS :P



Related Topics



Leave a reply



Submit