assign values to selective items using STL multimap - c++

typedef std::pair<int, bool> acq_pair; //edge, channel_quality
typedef std::pair<int, acq_pair> ac_pair;
typedef std::multimap<int, acq_pair> ac_map;
typedef ac_map::iterator It_acq;
int bits = acq_map.size();
std::cout << "bits = " << bits << std::endl;
std::vector<std::vector<bool> > c_flags (1 << bits);
for (i = 0; i < c_flags.size(); ++i)
{
for (j = 0; j < bits; ++j)
{
c_flags[i].push_back( (i & (1 << j)) > 0);
}
}
std::cout << "c_flags.size() = " << c_flags.size() << std::endl;
for(i = 0; i < c_flags.size(); ++i)
{
for(j = 0; j < bits; ++j)
{
std::cout << c_flags[i][j] << std::endl;
for(It_acq itc = acq_map.begin(); itc!= acq_map.end(); ++itc)
{
acq_pair it1 = itc->second;
itc->second.second = c_flags[i][j];
std::cout << itc->first << " : " << it1.first << " : " << it1.second << std::endl;
}
}
std::cout << "\n" << std::endl;
}
How can I access only one item from the multimap container at a time? I want to update only the jth value in the map, but when I iterate through the map all the bool values are changed. Is there a selective way to access the map container values?

The line itc->second.second = c_flags[i][j]; performed in a loop with itc from begin() to end() indeed performs assignment to every value of the map. If the goal was to modify only the j'th value in the map, there was no need for a loop over the entire map:
for(size_t j = 0; j < bits; ++j)
{
std::cout << c_flags[i][j] << std::endl;
It_acq itc = acq_map.begin(); // itc points at the beginning
advance(itc, j); // itc points at the j'th element
itc->second.second = c_flags[i][j]; // the assignment
for(It_acq itc = acq_map.begin(); itc!= acq_map.end(); ++itc)
{
acq_pair it1 = itc->second;
// itc->second.second = c_flags[i][j]; // no assignment here
std::cout << itc->first << " : " << it1.first << " : " << it1.second << std::endl;
}
}
If this map is used for indexed access in this manner, it may be worthwhile to consider switching to vector, though.

Related

How do I loop through a unordered_map in C++ without auto?

I am trying to loop through an unordered_map, to find if any of its VALUES is greater than 2. But this syntax is wrong
unordered_map<int, int> mp;
for (int i = 0; i < N; i++)
{
mp[arr[i]]++;
}
for (int i = 0; i < mp.size(); i++ ) {
cout << mp[i].second << " " << endl; //mp[i].second is wrong syntax
if (mp[i].second > 2) {
cout << "WRONG";
x = false;
break;
}
}
how can I do this?
It seems that you assumed(incorrectly) that mp[i] is std::pair<int, int> when in fact mp[i] gives you the mapped value which is of type int in your example. This can be seen from std::map::operator[]:
T& operator[]( Key&& key ); (2)
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
(emphasis mine)
Method 1
Since you don't want to use auto, you can explicitly write the type std::pair<int, int> in the range-based for loop as shown below:
//---------vvvvvvvvvvvvvvvvvvvvvvvv--------------------->not using auto here as you want
for (const std::pair<const int, int> &pair_elem: mp) {
cout << pair_elem.second << " " << endl;
if (pair_elem.second > 2) {
cout << "WRONG";
//other code here
}
}
Method 2
Note that you can also use std::find_if instead of a for loop as shown below:
auto iter = std::find_if(mp.begin(), mp.end(), [](const std::pair<int,int>& elem)
{ return elem.second > 2;});
if (iter != mp.end())
std::cout << "Greater found ";
else
{
std::cout<<"Greater not found"<<std::endl;
}
Demo
your question is missing a lot of information and literarily , if you searched on web , you would find many ways to loop over unordered_map in C++ , but anyways , here is the edited version of your code with a test case:
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
const int N = 10;
int arr[N] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
bool x = true;
unordered_map<int, int> mp;
unordered_map<int, int>:: iterator it;
for (int i = 0; i < N; i++)
{
mp[arr[i]]++;
}
mp[9] = 5;
for (it = mp.begin(); it != mp.end(); it++) {
cout << "key is " << it->first << " ,value is " << it->second << " " << endl;
if (it -> second > 2) {
cout << "WRONG";
x = false;
cout << "key is " << it->first << " ,value is " << it->second << " is greater than 2" << endl;
break;
}
}
return 0;
}

display string sub vector C++

I am new in C++, I created a struct called Device with two fields
string MacAdress
vector<string> RSSI
Then, I created a vector of structure: vector<Device> Devices
I want to extract the vector<string> RSSI and display its contant.
Here is where I got stuck in my main.cpp:
cout << "display MAC and RSSI"<< endl;
Device CurrentDevice;
for(int j=0; j<Devices.size();j++)
{
CurrentDevice = Devices.at(j);
vector<string>::const_iterator begin = CurrentDevice.GetRSSIs().begin();
vector<string>::const_iterator last = CurrentDevice.GetRSSIs().begin() + CurrentDevice.GetRSSIs().size();
vector<string> intermed(begin+1, last);
cout << "Size: "<< intermed.size() << endl;
for (int i = 0 ; i < intermed.size(); i++)
{
cout << intermed[i] << endl;
cout << "device n°"<< j+1<<" " << "MAC "<< " "<< CurrentDevice.GetMacAdress()<< endl;
for(int k=0; k<intermed.size();k++)
{
cout << "device n°" << j;
cout << "\tRSSI " << k << " = " << intermed.at(k)<< endl;
}
}
return 0;
}
I end up with Size=0
here is some simplified code that does not use iterators but should still do the job:
#include <iostream>
#include <string>
#include <vector>
int main()
{
struct Device {
std::string MacAddress;
std::vector<std::string> RSSI;
};
std::vector<Device> Devices;
// add some stuff to first object
Device CurrentDevice1;
CurrentDevice1.MacAddress = "A-B-C";
CurrentDevice1.RSSI.push_back("rssi11");
CurrentDevice1.RSSI.push_back("rssi12");
CurrentDevice1.RSSI.push_back("rssi13");
Devices.push_back(CurrentDevice1);
// add some stuff to second object
Device CurrentDevice2;
CurrentDevice2.MacAddress = "D-E-F";
CurrentDevice2.RSSI.push_back("rssi21");
CurrentDevice2.RSSI.push_back("rssi22");
Devices.push_back(CurrentDevice2);
// see object MAC's
for (int i = 0; i < Devices.size(); i++){
std::cout << "device " << i+1 << " MAC: " << Devices[i].MacAddress << std::endl;
}
// see object RSSI's
for (int j = 0; j < Devices.size(); j++){
for (int k = 0; k < Devices[j].RSSI.size(); k++){
std::cout << "device " << j + 1 << " RSSI: " << k +1 << " : " << Devices[j].RSSI[k] << std::endl;
}
std::cout << "\n";
}
return 0;
}
I'm not sure about what do you want to obtain, but I suppose the problem is in the following lines
vector<string>::const_iterator last = CurrentDevice.GetRSSIs().begin() + CurrentDevice.GetRSSIs().size();
vector<string> intermed(begin+1, last);
Do you want to obtain a copy of CurrentDevice.GetRSSIs()?
In this case, you can use begin() and end()
vector<string> intermed(CurrentDevice().GetRSSIs().begin(),
CurrentDevice().GetRSSIs().end());
or, simpler, invoke the copy constructor,
vector<string> intermed(CurrentDevice().GetRSSIs());

Inserting list elements to vector, getting additional unwanted values C++

In my C++ script, I want to insert some elements of a list into a vector (from the beginning of list to a specific position "it"), and then try to add the vector at the top of the list and keeping the same order of the vector but I get unwanted additional elements in the vector.
Here is my code:
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
int main() {
std::list<int> mylist;
for (int i = 0; i < 10; i++)
mylist.push_back(i * 10);
for (std::list<int>::iterator i = mylist.begin(); i <= mylist.end(); ++i) {
std::cout << *i << ", ";
}
std::cout << std::endl;
std::advance(it, 6);
std::cout << "The 6th element in mylist is: " << *it << std::endl;
// The vector that will contain mylist elements
std::vector<int> intAdeplacer;
intAdeplacer.insert(intAdeplacer.end(), mylist.begin(), it);
std::cout << std::endl;
std::cout << "Nombre d'éléments dans le vecteur : " << intAdeplacer.size() << std::endl;
std::cout << std::endl;
// see the content of the vector
std::cout << "Le vecteur de deplacement contient : " << std::endl;
for (std::vector<int>::const_iterator i = intAdeplacer.begin();
i <= intAdeplacer.end(); ++i) {
std::cout << *i << ", ";
}
I get this output:
Le vecteur de deplacement contient :
0, 10, 20, 30, 40, 134985,
134985 is not wanted..
// Insert in front of the list the values of the vector and keeping the same order of elements in the vector
for (std::vector<int>::const_iterator i = intAdeplacer.end();
i >= intAdeplacer.begin(); --i) {
mylist.push_front(*i);
}
std::cout << std::endl;
std::cout << std::endl;
std::cout << "nouvelle composition de mylist : " << std::endl;
for (std::list<int>::const_iterator j = mylist.begin(); j != mylist.end();
++j) {
std::cout << *j << ", ";
}
std::cout << std::endl;
std::cout << std::endl;
// erasing the added elements from mylist
std::list<int>::iterator debut = mylist.begin();
std::list<int>::iterator fin = mylist.end();
std::advance(fin, 6);
mylist.erase(debut, fin);
for (std::list<int>::iterator j = mylist.begin(); j <= mylist.end(); ++j) {
std::cout << *j << ", ";
}
return 0;
}
If it is an iterator pointing at the 6th element of your list, the following insert() will insert from begin() (included) to it (excluded) into the vector:
intAdeplacer.insert(intAdeplacer.end(), mylist.begin(), it);
So you'll have only 5 elements, from 0 to 40. Unfortunately your printing loop does include the end() of the vector, which is out of range. This is why you get this strange trailing number.
Just correct your loop into:
for (auto i = intAdeplacer.begin(); i != intAdeplacer.end(); ++i) {
std::cout << *i << ", ";
}
Or consider this alternate range-for syntax:
for (auto &element: intAdeplacer) {
std::cout << element << ", ";
}

C++: Copying an element from an unordered_set to a vector

Background: I am implementing the nearest neighbor algorithm for the Traveling-Salesman-Problem. I need to calculate the distance traveled for the tour as well as keep track of the order of points visited. I have defined a point class with instance variables x and y and a function calcDist for calculating the distance between two points. I start by storing all of the points in a std::unordered_set named points, creating an empty std::vector named path to store the tour path, and assigning the starting point to startPoint, and pass these to my nearestNeighbor() function:
void nearestNeighbor(unordered_set<Point, PointHasher> points, vector<Point> &path, Point startPoint) {
// Declare variables
unordered_set<Point, PointHasher>::iterator it;
Point currentLocation, possibleNeighbor, nearestNeighbor;
double totalDist = 0;
int pointsCount = path.capacity() - 1;
// Set the starting location
it = points.find(startPoint);
currentLocation = *it;
path[0] = currentLocation;
points.erase(currentLocation);
cout << "Start location: " << path[0].x << ", " << path[0].y << endl;
// Create the path
for (int i = 1; points.size() > 0; i++) {
double minDist = -1;
// Find the current location's nearest neighbor
for (it = points.begin(); it != points.end(); it++) {
possibleNeighbor = *it;
int currentDist = currentLocation.calcDist(possibleNeighbor);
if (minDist == -1 || currentDist < minDist) {
minDist = currentDist;
nearestNeighbor = possibleNeighbor;
}
}
// Record nearest neighbor data and prepare for the next iteration
currentLocation = nearestNeighbor;
path[i] = currentLocation;
points.erase(currentLocation);
totalDist += minDist;
cout << "Nearest neighbor: " << path[i].x << ", " << path[i].y << endl;
}
// Return to the starting location
path[pointsCount] = startPoint;
cout << "End location: " << startPoint.x << ", " << startPoint.y << endl;
cout << "Path:" << endl;
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
cout << "Total distance: " << totalDist << endl;
}
The problem is that once the program exits the outer for loop, all the points in path are overwritten somehow. To see what I mean, here is the output:
Start location: 3, 4
Nearest neighbor: 6, 8
Nearest neighbor: 11, 7
Nearest neighbor: 50, 8
End location: 3, 4
Path:
3, 4
3, 4
3, 4
3, 4
3, 4
Total distance: 49
Press any key to continue . . .
I am thinking this either has to be a problem with pointers/addresses of the vector elements, or something with scope since the problem happens after exiting the for loop. I have even tried printing the path[1] after each iteration to see when it gets changed, but it is correct throughout the loop, and only changes in the output at the end. Any thoughts? I am stumped. And if you have made it this far, thank you very much for your time.
you are always outputing the coordinates of path[0] man
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
You have
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
This doesn't iterate through i. Change your 0 to i and you'll likely see something more helpful:
for (int i = 0; i < path.size(); i++) {
cout << path[i].x << ", " << path[i].y << endl;
}
Edit: Change path[i] = currentLocation; to path.push_back(currentLocation); - this will automatically increase the size of your path vector to fit the new elements.
void nearestNeighbor(
unordered_set<Point, PointHasher> points,
vector<Point> &path,
Point startPoint,
double &totalDist) // note the new variable passed here
{
// Declare variables
unordered_set<Point, PointHasher>::iterator it;
Point currentLocation, possibleNeighbor, nearestNeighbor;
// double totalDist = 0; Remove this line
// int pointsCount = path.capacity() - 1; And this
// Set the starting location
it = points.find(startPoint);
currentLocation = *it;
path.push_back(currentLocation); // Changed this line
points.erase(currentLocation);
cout << "Start location: " << path[0].x << ", " << path[0].y << endl;
// Create the path
for (int i = 1; points.size() > 0; i++) {
double minDist = -1;
// Find the current location's nearest neighbor
for (it = points.begin(); it != points.end(); it++) {
possibleNeighbor = *it;
int currentDist = currentLocation.calcDist(possibleNeighbor);
if (minDist == -1 || currentDist < minDist) {
minDist = currentDist;
nearestNeighbor = possibleNeighbor;
}
}
// Record nearest neighbor data and prepare for the next iteration
currentLocation = nearestNeighbor;
path.push_back(currentLocation); // And this line
points.erase(currentLocation);
totalDist += minDist;
cout << "Nearest neighbor: " << path[i].x << ", " << path[i].y << endl;
}
// Return to the starting location
path.push_back(startPoint); // And here also!
cout << "End location: " << startPoint.x << ", " << startPoint.y << endl; // This I didn't change,
// but perhaps you should make it reflect the last point in the vector,
// not the start point which is supposed to be the last point in the vector
cout << "Path:" << endl;
for (int i = 0; i < path.size(); i++) {
cout << path[i].x << ", " << path[i].y << endl;
}
cout << "Total distance: " << totalDist << endl;
}
I do not see any place which grows the size of the path vector.
I suspect that you're passing an empty std::vector, for the second argument, and as soon as you hit path[0]=currentLocation; ... undefined behavior.
Also, I don't think that capacity() does what you think it does.
That, and, as others have pointed out, you're not outputing the contents of the array correctly, but that's a minor problem. The major problem here is that this program is likely scribbling over and corrupting the heap.

Print a vector of maps

how do I print a vector of multimaps?
for example I have a vector that looks like this:
typedef std::multimap<double,std::string> resultMap;
typedef std::vector<resultMap> vector_results;
EDIT
for(vector_results::iterator i = vector_maps.begin(); i!= vector_maps.end(); i++)
{
for(vector_results::iterator j = i->first.begin(); j!= i->second.end(); j++)
{
std::cout << j->first << " " << j->second <<std::endl;
}
}
The i variable in the outer for loop points to a resultMap, which means the type of the j variable needs to be resultMap::iterator. Rewrite your loops as
for(vector_results::const_iterator i = vector_maps.begin(); i != vector_maps.end(); ++i)
{
for(resultMap::const_iterator j = i->begin(); j != i->end(); ++j)
{
std::cout << j->first << " " << j->second << std::endl;
}
}
I changed the iterator type to const_iterator since the iterators are not modifying the container elements.
If your compiler supports C++11's range based for loops, the code can be written much more succinctly
for( auto const& i : vector_maps ) {
for( auto const& j : i ) {
std::cout << j.first << " " << j.second << std::endl;
}
}