Is there a built-in method that removes and element (i.e. from map given a key) and returns the removed element?
There is no built-in method to do this, you can however store the element by accessing it and then erase it.
Erasing requires you to specify key.If it's a multi-map you should erase with position.
Here is a function you can use (C++11):
#include <iostream>
#include <map>
template<typename T>
typename T::mapped_type removeAndReturn(T& mp, const typename T::key_type& val) {
auto it = mp.find(val);
auto value = std::move(it->second);
mp.erase(it);
return value;
}
int main() {
std::map<int, int> m;
m[3] = 4;
std::cout << "Map is empty: " << std::boolalpha << m.empty() << std::endl;
std::cout << "Value returned: " << rm_and_return(m, 3) << std::endl;
std::cout << "Map is empty: " << std::boolalpha << m.empty() << std::endl;
}
Output:
Map is empty: false
Value returned: 4
Map is empty: true
Related
First one being:
map <int,int> m;
//... some elements inserted
auto i= m.begin();
cout<<(*i).first<<(*i).second;
Here we are required to use the dereference operator *
Second:
map <int,int> m;
//... some elements inserted
for(auto i: m)
cout<<i.first<<i.second;
Why am I not required to use the * operator this time?
One more doubt:
for(auto &i: m)
what difference does '&' make here?
auto i=m.begin() will give you iterator .. which is accessed more like a pointer (syntactically) when you want to access the value...
for(auto i:m) will copy current element of m (a pair) into i , i is a copy of element, not the element itself...
for (auto &i: m) will work on a reference, the original map is affected
As explained in the below code snippet, the first i is of type iterator where as the i in the for loops are of pair type.
#include <iostream>
#include <map>
int main()
{
std::map <int,int> m;
m[1] = 5;
m[10] = 60;
m[100] = 800;
// Below i is map iterator (std::map<int, int>::iterator)
auto i = m.begin();
std::cout << typeid(i).name() << '\n';
std::cout << (*i).first << " : " << (*i).second << '\n';
std::cout << i->first << " : " << i->second << '\n';
for(auto i: m) {
// Below i is pair<int, int>
std::cout << typeid(i).name() << '\n';
std::cout << i.first << " : " << i.second << '\n';
}
for(auto& i: m) {
// Below i is reference of pair<int, int>)
// modifying this would result in updated values in the map.
std::cout << typeid(i).name() << '\n';
std::cout << i.first << " : " << i.second << '\n';
}
return 0;
}
Given the following code:
#include <vector>
#include <iostream>
struct number {
int n{666};
};
int main()
{
std::vector<number> vec;
std::cerr << vec.size() << std::endl;
number n;
vec.push_back(n);
std::cerr << vec.size() << std::endl;
auto b = std::move(vec.front());
std::cerr << "b: " << b.n << std::endl;
std::cerr << vec.size() << std::endl;
}
I get the following output:
0
1
b: 666
1
Shouldn't the last 1 be 0?
std::move doesn't even know that the thing it moved was in a container. The block of memory that the vector owns is still there, just in an unspecified state. It's up to you to manage the vector.
Once you have used the value at the front and you want to get rid of it you will need to erase it from the vector. I won't talk about the front() returning a ref as 0x5453 mentioned that. But there is no reason to use std::move there - all that does is cast the value to a rvalue reference it does not actually "move" anything on its own.
#include <vector>
#include <iostream>
struct number {
int n{666};
};
int main()
{
std::vector<number> vec;
std::cerr << vec.size() << std::endl;
number n;
vec.push_back(n);
std::cerr << vec.size() << std::endl;
// Since this is a ref, and your struct is simple - just copy
auto b {vec.front()};
// Now remove the element
vec.erase(vec.begin());
std::cerr << "b: " << b.n << std::endl;
std::cerr << vec.size() << std::endl;
}
I've installed CodeBloks and I was testing it with a simple problem.
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
unordered_map<int,int> mp;
mp[1]=2;
mp[2]=3;
for(unordered_map<int,int>::iterator it = mp.begin();it!=mp.end();it++)
cout<<*it<<" ";
return 0;
}
I get this error:
cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
Taken from cppreference
for( const auto& n : u ) {
std::cout << "Key:[" << n.first << "] Value:[" << n.second << "]\n";
}
A map (unordered or not) is composed of a key, and a value. You can access it with first and second from the iterator.
The error may be misleading. The actual problem is that unordered map iterates in pairs of keys and values, and there is no << operator for printing these pairs directly.
You can access the key through it->first and the value through it->second:
for(unordered_map<int,int>::iterator it = mp.begin();it!=mp.end();it++)
cout<<it->first << " " << it->second << endl;
Demo.
A map stores key/value-pairs, and it provides a member first (standing for the key) and a member second (standing for the value). Try the following cout...-statement:
cout << it->first << ":" << it->second << " ";
Structured bindings would work nicely for this:
for(auto [first, second] : mp) {
cout << first << '\t' << second << '\n';
}
I am wanting to iterate through my entire column that contains the type double and divide each value by the size of the column. This will give me the frequency. I would have not issue doing this in an array or any other datatype. I am still learning about the vectors. Here is the 2D vector type that I am trying to manipulate
vector<pair<char, double>> output;
If you have C++11:
for (auto & p : output)
{
cout << p.first << " " << p.second << "\n";
}
std::cout << std::endl;
or with C++03
for (std::vector<std::pair<char, double> >::iterator it = output.begin();
it != output.end(); ++it)
{
cout << it .first << " " << it .second << "\n";
}
std::cout << std::endl;
You can treat a vector just like an array, and access the elements using []. For example:
for (size_t i = 0; i < output.size(); ++i)
{
pair<char, double>& element = output[i]; // access element i in the vector
cout << element.first; // prints the first member of the pair
cout << element.second; // prints the second member of the pair
}
std::pair is a struct template that provides a way to store two
heterogeneous objects as a single unit.
if you have a vector of pairs this means you will access data through pair interface . You can get first data of pair via first member and second via second.
for(std::vector<std::pair <char, double> >::const_iterator vpci = arg.begin();
vpci != arg.end(); ++vpci) {
cout << vpci->first << "->" << vpci->second;
}
or even better, maybe create a template:
template <typename T1, typename T2>
void prn_vecOfPair(const std::vector<std::pair <T1, T2> > &arg, string sep ="") {
for(std::vector<std::pair <T1, T2> >::const_iterator vpci = arg.begin();
vpci != arg.end(); ++vpci) {
cout << vpci->first << "->" << vpci->second << sep;
}
}
in C++11 this (as usual) can be done much easier:
for (auto & i : output)
{
cout << i->first << "->" << i->second << "\n";
}
void main()
{
typedef boost::ptr_map<int, char> MyMap;
//typedef std::map<int, char *> MyMap; // in contrast with std type it works
MyMap mymap;
mymap[1] = new char('a');
mymap[2] = new char('b');
mymap[3] = new char('c');
BOOST_FOREACH(MyMap::value_type value, mymap)
{
std::cout << value.first << " " << value.second << std::endl;
}
MyMap const & const_mymap = mymap;
BOOST_FOREACH(const MyMap::value_type value, const_mymap)
{
std::cout << value.first << " " << value.second << std::endl;
}
}
The following error message comes from GCC at the second BOOST_FOREACH
error: conversion from 'boost::ptr_container_detail::ref_pair<int, const char* const>' to non-scalar type 'boost::ptr_container_detail::ref_pair<int, char* const>' requested
I reckon that this is the weakness of the pointer container's ref_pair...
Based on this answer, it looks like you're right. But there's a workaround. Change your second loop to this:
BOOST_FOREACH(MyMap::const_iterator::value_type value, const_mymap)
{
std::cout << value.first << " " << value.second << std::endl;
}
Typedefing is also confusing when using maps. Its much simpler(and much more readable) to use a tuple instead. Here's how you can use a tuple:
int key;
char* value;
BOOST_FOREACH(boost::tie(key, value), mymap)
{
std::cout << key << " " << value << std::endl;
}
Plus, you can give more meaningful names instead of value.first and value.second.