I've been googling for this for so long but I couldn't get the answer. The most of sample that I found are based on iterating with vector, map and etc..
I have the code below.
multimap<int, int>::iterator it = myMuliMap.find(1);
Let's say I have three pairs that has key "1". I like to get those three pair from for loop.. I think that I can't use for(multimap::iterator anotherItr=myMuliMap.begin()..
The following code is in C#.. I like to get C++ version.. Thanks.
foreach(var mypair in it){
Console.WriteLine(mypair.Key);
}
The function you're looking for is equal_range. This returns an iterator to all pairs in the map which match the specified key
auto range = myMultiMap.equal_range(1);
for ( auto it = range.first; it != range.second; ++it) {
...
}
EDIT
Version without auto
pair<multimap<int,int>::const_iterator,multimap<int,int>::const_iterator>> it = myMultiMap.equal_range(1);
for ( multimap<int,int>::const_iterator it = range.first;
it != range.second;
++it) {
...
}
Use std::equal_range():
int tolookfor = 1;
typedef multimap<int, int>::iterator iterator;
std::pair<iterator, iterator> p =
std::equal_range(myMuliMap.begin(), myMuliMap.end(), tolookfor);
for (iterator it = p.first; it != p.second ++it)
std::cout << (*it).second << std::endl;
the multi_map's member function equal_range works similarily:
std::pair<iterator, iterator> p =
myMuliMap.equal_range(tolookfor);
This will print out only the values found by
std::pair<std::multimap<int, int>::iterator, std::multimap<int, int>::iterator> result;
result = myMultimap.equal_range(1);
for(std::multimap<int,int>::iterator it = result.first; it != result.second; it++)
{
std::cout << it->first << " = " << it->second << std:: endl;
}
You can use something like the following loop.
for (std::multimap<int, int>::iterator i = myMultiMap.lower_bound(1);
i != myMultiMap.upper_bound(1);
++i)
{
std::cout << i->first << " => " << i->second << '\n';
}
This is valid in the current version of C++.
Related
I am searching for all pairs for a particular key in a multimap using the code below.
int main() {
multimap<int,int> mp;
mp.insert({1,2});
mp.insert({11,22});
mp.insert({12,42});
mp.insert({1,2});
mp.insert({1,2});
for (auto itr = mp.find(1); itr != mp.end(); itr++)
cout << itr->first<< '\t' << itr->second << '\n';
}
You're calling find only a single time in your code. It's perfectly acceptable for this call to return the same value as mp.begin() resulting in you iterating though all the entries in the map before reaching mp.end().
You can use the equal_range member function to get iterators for the start and end of the elements with key 1:
for (auto[itr, rangeEnd] = mp.equal_range(1); itr != rangeEnd; ++itr)
{
std::cout << itr->first<< '\t' << itr->second << '\n';
}
Like others pointed out your code looped all the elements, from the first iterator (find(1) retuned the first iterator) to last.
If you want you can use C++20 ranges (#include <ranges>)
//DATA
std::multimap<int, int> mp;
mp.insert({ 1,2 });
mp.insert({ 11,22 });
mp.insert({ 12,42 });
mp.insert({ 1,3 });
mp.insert({ 1,4 });
//FILTER THE ELEMENTS
auto foundElements = mp | std::views::filter([](auto& v) {
return v.first == 1;
});
//PRINT
for (auto m : foundElements)
{
std::cout << m.first << " " << m.second << std::endl;
}
I need to iterate over the entire map without stopping the loop.
My example works but it uses two loops, can this be fixed?
I think it's possible to do this using only one for loop
#include <map>
map<int, int>map2;
map2[1] = 11;
map2[2] = 12;
map2[3] = 13;
for (;;)
{
for (auto& a : map2)
{
cout << a.first << " : " << a.second << '\n';
}
}
Use the std::map::iterator. That way you can just check if the iterator is at the end and if so reset it to the beginning.
map<int, int>::iterator it;
for ( it = map2.begin(); it != map2.end(); it == std::prev( map2.end() ) ? it = map2.begin() : it++ )
{
cout << it->first << " : " << it->second << '\n';
}
Clarification
it == std::prev( map2.end() ) ? it = map2.begin() : it++
That is the ternary operator. You first ask if the iterator is equal to the last element in the map. We add the std::prev() in order to get the last element as map::end() provides us with a past-the-end value.
it == std::prev(map2.end())
If it is the last element you set the iterator to the beginning of the map.
it = map2.begin()
Else the iterator is incremented and you get the next element
it++
See also: Loop through map
I have no match for operator in map iterator. When I try to make the iterator it points to the map end-1.
#include <iostream>
#include <map>
int main()
{
std::map<char,int> mymap;
mymap['b'] = 100;
mymap['a'] = 200;
mymap['c'] = 300;
// show content:
for (std::map<char,int>::iterator it=mymap.begin(); it!=mymap.end()-1; ++it){
std::cout << it->first << " => " << it->second << '\n';
}
return 0;
}
This statement
mymap.end()-1
is only legal for Random Access Iterator but std::map::iterator is Bidirectional Iterator. If you want to skip last element use std::prev()
for (std::map<char,int>::iterator it=mymap.begin(); it!=std::prev( mymap.end() ); ++it)
though it is not efficient to always calculate it and it should be instead:
auto end = std::prev( mymap.end() );
for (auto it=mymap.begin(); it!=end; ++it) ...
Note for this to work you have to be sure that there is at least one element in your map. If you do not want to skip the last element remove -1 completely.
There's no operator- for map iterators, but it doesn't matter because if you want to show all the content is should be just it!=mymap.end();
Pretty new to C++, only at it a week or so, I want to iterate through a set of nested sets and write each element in the inner set to a line in a file.
Each inner set has 3 elements and I want all three elements on the same line.
I have a set up as follows:
// Define "bigSet" and initiate as empty set "Triplets"
typedef set < set<string> > bigSet;
bigSet Triplets;
I tried something of this sort to go through it but it gives me an error...
// Iterate through and print output
set <string>::iterator it;
for(it = Triplets.begin(); it != Triplets.end(); it++){
cout << *it << endl;
}
Any help is greatly appreciated guys thank you!
I would do it this way:
// Iterate through and print output
set < set <string> >::iterator it_ex; // iterator for the "outer" structure
set <string>::iterator it_in; // iterator for the "inner" structure
for(it_ex = Triplets.begin(); it_ex != Triplets.end(); it_ex++)
{
for(it_in = it_ex->begin(); it_in != it_ex->end(); it_in++)
cout << *it_in << ", ";
cout << endl;
}
Triplets is not a set<string>; it is a set<set<string>>; each item in Triplets is itself a set, than can contain several strings.
The iterator must match the type of the container; with two levels of nested containers, you should iterate twice:
set<set<string>>::iterator it;
set<string>::iterator it2;
for(it = Triplets.begin(); it != Triplets.end(); it++) {
for (it2 = it->begin(); it2 != it->end(); ++it2) {
cout << *it2 << endl;
}
}
Triplets is type set < set<string> > and therefore requires an iterator of type set < set<string> >::iterator or bigSet::iterator. It isn't type set <string>. You could also use const_iterator.
Note that iterating Triplets gives you an iterator to another set, and not a string.
Also consider
for (const auto& i : Triplets)
{
for (const auto& j : i)
{
cout << j << endl;
}
}
You have an error because Triplets.begin() is not of type set<string>::iterator, it's set<set<string>>::iterator.
What you need to do is have two loops: one for iterating over the outer set and one for the inner.
set<set<string>>::iterator it;
for(it = Triplets.begin(); it != Triplets.end(); ++it)
{
set<string>::iterator it2;
for(it2 = it->begin(); it2 != it->end(); ++it2)
{
cout << *it2;
}
cout << endl;
}
If you use increment/decrement operators (++/--) on iterators, it might be better to use the prefix versions (++it) instead of the suffix ones (it++). This is because the suffix ones create a copy of the iterator before it is incremented (and that copy is then returned) but in cases like this, you have no need for it.
Moreover, if you're using C++11, you can use the range-based for loops and auto keyword, which simplify things a lot:
for(const auto &innerSet : Triplets)
{
for(const auto &innerSetElement : innerSet)
{
cout << innerSetElement;
}
cout << endl;
}
First: if they're triplets, are you sure that std::set is the type you
want for the inner values. Perhaps a class would be more
appropriate, in which case, you define an operator<< for the `class,
and your simple loop works perfectly. Something like:
class Triplet
{
std::string x;
std::string y;
std::string z;
public:
// Constructors to enforce that none of the entries are identical...
// Accessors, etc.
friend std::ostream& operator<<( std::ostream& dest, Triplet )
{
dest << x << ", " << y << ", " << z;
return dest;
}
};
And then to output:
for ( Triplet const& elem : Triplets ) {
std::cout << elem << std::endl;
}
Otherwise: you need to define the format you want for the output. In
particular, you'll probably want a separator between the strings in the
line, for example. Which means you probably cannot use a range based
for, at least not for the inner loop. You would need something like:
for ( std::set<std::string> const& triplet : Triplets ) {
for ( auto it = triplet.cbegin(); it != triplet.cend(); ++it ) {
if ( it != triplet.cebegin() ) {
std::cout << ", ";
}
std::cout << *it;
}
std::cout << std::endl;
}
(If the set of triplets is large, you'll definitely want to consider
replacing std::endl with '\n'. But of course, if it is really
large, you probably won't be outputting to std::cout.)
I hav two stl maps like map<int,int> and i want to compare them.. so here is the code..
map <int, int> a,b;
insert into a and b;
map<int,int>::iterator i;
for(i=a.begin();i!=a.end();i++){
if(what should be here?)
then cout << (*i).first << " also present in b" << endl;
}
I was hoping that something like (b[(*i).first]).exist??
Use map::find as:
for(i=a.begin(); i!=a.end(); i++)
{
if( b.find(i->first) != b.end() )
std::cout << (*i).first << " also present in b" << std::endl;
}
Note i->first and (*i).first are same.
Use map::find().
This will return true if i->first (the key of the element in a pointed by i) is present in b.
if (b.find(i->first) != b.end())
You can't use operator[], because that will create the key if it doesn't exist. Instead, use find:
map<int,int>::const_iterator it = b.find(a->first);
if( it == b.end() )
// NOT FOUND
std::map has a function named find for finding a key in the map. See this
So the code should be :
if( b.find( i->first ) != b.end() )
I like b.count(i->first) > 0.
map::find function
I will do as this :
std::map <int, int> a,b;
insert into a and b;
std::map<int,int>::iterator it = a.begin();
std::map<int,int>::iterator ite = a.end();
while (it != ite)
{
if (b.find(it->first) != b.end())
{
std::cout << it->first << " also present in b" << std::endl;
}
++it;
}
For your task for performance reasons I would suggest something like:
map<int,int>::iterator ia = a.begin(), ib = b.begin(),
iae = a.end() , ibe = b.end();
while(ia != iae && ib != ibe) {
if (ia->first < ib->first) ia++;
else if (ia->first > ib->first) ib++;
else {
cout << ia->first << " also present in b" << endl;
ia++; ib++;
}
}