How to Loop Through a C++ Map of Maps

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;
}
}

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 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.

Groovy iterate over Map of maps

Depends why you want to do it, but you could grab the values and flatten them:

image_map.values().flatten().each {
println it
}

So with the added requirement in the comment, you could do:

image_map.collectMany { k, v -> v.collect { "${k}.method($it)" } }
.each { println it }

To print

obj_1.method(1)
obj_1.method(2)
obj_2.method(3)
obj_2.method(4)

Edit 2 with another requirement... Assuming the keys ARE the objects (and not strings):

def obj_1 = [method: { it -> "I am obj1 $it" }]
def obj_2 = [method: { it -> "I am obj2 $it" }]

image_map = [(obj_1): ['1','2'], (obj_2): ['3','4']]

image_map.collectMany { k, v -> v.collect { [object: k, param: it] } }
.each { println it.object.method(it.param) }

Prints:

I am obj1 1
I am obj1 2
I am obj2 3
I am obj2 4

Create a template to iterate map in C++11 like C++17's structured bindings

You cannot initialize variables inside the range-based loop until C++20, so the best option, that I can see to use such macro:

#define STRUCTURED_BINDING(a, b, map_item) \
const auto &a = map_item.first; \
const auto &b = map_item.second;

So then in your code, you can write something like that:

for(const auto& item: a)
{
STRUCTURED_BINDING(fst, snd, item);
std::cout << fst << " " << snd << std::endl;
}

You can improve this macro to be used with tuple (get<0>, get<1>, ...), rewriting macro to use variadic arguments.

Iterating map of vectors of different sizes in C++

For multiple reasons you should be using an iterator.

  1. Your map may not contain every element from 0 to drawingPoints.size() and for each element that it doesnt contain when you loop over it you will create it.
  2. Your highest entry may be greater then drawingPoints.size() in which case you will never reach it.

Lets look at outer most loop, if you want to define an iterator for it you should do the following:

for (mapPoints::Iterator it = drawingPoints.begin(); it != drawingPoints.end(); it++) {

This creates an iterator which you can look at (by doing it-> or *it).

More information can be found here.

Iterate through updating F# Map vs a C# Dictionary

Fold is a general technique to manipulate state in an immutable iterative/recursive way. If you want to experiment with it in C# it's the Aggregate LINQ extension method.

In F# Map.add is actually add/replace, so you don't need to branch based on whether the key is contained.

type node = {myFloat:float; data1:int; data2:int;}
type nodesCollection = {metaData:int; nodes:Map<float,node>}

let nodeColl = { metaData = 5; nodes = Map.empty }
let results : (node * int * int * int * int) List = []

let nodes = List.map (fun (n, _, _, _, _) -> n) results

let res = List.fold (fun map e -> Map.add e.myFloat e map) nodeColl.nodes nodes


Related Topics



Leave a reply



Submit