Range of the first element of a vector pair - c++

I need to find the range of the first elements of a vector pair. I need this range for a map, which counts the duplicate entries in this vector.
Here is a code snipped and how I managed it. Maybe there is another, better solution?
unordered_map<int, int> frequency;
vector<pair<unsigned int,Point>> Roi_Num_Koord;
vector<int> Roi_first_Element;
int main()
{
// Part1: fill the Vector pair
Roi_Num_Koord.emplace_back(make_pair(0,Point(3.6));
Roi_Num_Koord.emplace_back(make_pair(1,Point(4,8));
Roi_Num_Koord.emplace_back(make_pair(2,Point(8.3));
Roi_Num_Koord.emplace_back(make_pair(3,Point(4,6));
// Part 2: now copy the first element to another vector
for (int i = 0; i < Roi_Num_Koord.size(); i++)
{
Roi_first_Element.emplace_back(Roi_Num_Koord[i].first);
}
// Part 3: now do the duplicate search (Code was taken out of the internet)
for (int i : Roi_first_Element)
{
++frequency[i];
cout << "freque "<<frequency[i] << endl;
}
for (const auto& e : frequency)
{
if (e.second == 5)
{
std::cout << "Roi " << e.first << " encountered " << e.second << " times\n";
}
}
}
So is there a possibility to remove Part 2 and find out the range of the first Element of Roi_Num_Koord?, so that I don't have to copy the first elements of this vector to the other vector (Roi_first_Element)

Yes the second step is completely redundant. You just iterate through the container and whenever you need first element of the pair you say it explicitly pretty much like you do in Step 2.
for(const pair<unsigned int,Point>& element : Roi_Num_Koord)
{
++frequency[element.first];
cout << "freque " << frequency[element.first] << endl;
}

Related

frequency <unordered_map> behaviour

i try to implement freq unordered map but it has weird behavior , why when i use unordered_map it gives me keys with negative numbers and when i use map it will give my the correct keys values.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int maxOperations(vector<int>& nums, int k) {
unordered_map <int,int> mp;
for(auto i:nums){
mp[i]++;
}
int count=0;
// for(auto i:mp)
// cout << i.first << " " << i.second << endl;
for(auto i:mp){
int target= k-i.first;
cout << i.first << " " << i.second << " "<< mp[target] << endl;
if(i.second>0 && mp[target]>0){
if(i.first!=target){
count += min(i.second,mp[target]);
mp[target]=0;
//i.second=0;
mp[i.first]=0;
}else
{
cout << count << endl;
count += floor(i.second/2);
mp[target]=0;
}
}
}
return count;}
int main()
{
vector<int> vec= {29,26,81,70,75,4,48,38,22,10,51,62,17,50,7,7,24,61,54,44,30,29,66,83,6,45,24,49,42,31,10,6,88,48,34,10,54,56,80,41,19};
int k =12 ;
cout << maxOperations(vec,k);
return 0;
}
When you use an ordered map, you traverse the keys in order. Thus, target is never negative. When you traverse an unordered map, it is unordered. Therefore, target is sometimes negative.
If the negative values are not correct, then you need to traverse the map in order and so you should not use an unordered map.
Another problem with traversing out of order is that when modifying the map while traversing it, you will create entries that may or may not be included in your traversal. That will cause unpredictable behavior. You may prefer to create new entries in a separate container and merge them into the original container only when you're finished traversing.

How to get the elements of a tuple

I am creating a scrabble game and i need to have a basic score to words on the dictionary.
I used make_tuple and stored it inside my tuple. Is there a way to access elements in a tuple as if it was in a vector?
#include <iostream>
#include <tuple>
#include <string>
#include <fstream>
void parseTextFile()
{
std::ifstream words_file("scrabble_words.txt"); //File containing the words in the dictionary (english) with words that do not exist
std::ofstream new_words_file("test.txt"); //File where only existing words will be saved
std::string word_input;
std::tuple<std::string, int> tupleList;
unsigned int check_integrity;
int counter = 0;
while(words_file >> word_input)
{
check_integrity = 0;
for (unsigned int i = 0; i < word_input.length(); i++)
{
if((int)word_input[i] >= 97 && (int)word_input[i] <= 123) //if the letter of the word belongs to the alphabet
{
check_integrity++;
}
}
if(word_input.length() == check_integrity)
{
new_words_file << word_input << std::endl; //add the word to the new file
tupleList = std::make_tuple(word_input, getScore(word_input)); //make tuple with the basic score and the word
counter++; //to check if the amount of words in the new file are correct
std::cout << std::get<0>(tupleList) << ": " << std::get<1>(tupleList) << std::endl;
}
}
std::cout << counter << std::endl;
}
One would generally use a tuple when there are more than two values of different types to store. For just two values a pair is a better choice.
In your case what you want to achieve seems to be a list of word-value pairs. You can store them in a container like a vector but you can also store them as key-value pairs in a map. As you can see when following the link, an std::map is literally a collection of std::pair object and tuples are a generalization of pairs.
For completeness, if my understanding of your code purpose is correct, these are additions to your code for storing each tuple in a vector - declarations,
std::tuple<std::string, int> correct_word = {};
std::vector<std::tuple<std::string, int>> existing_words = {};
changes in the loop that saves existing words - here you want to add each word-value tuple to the vector,
if(word_input.length() == check_integrity)
{
// ...
correct_word = std::make_tuple(word_input, getScore(word_input));
existing_words.push_back(correct_word);
// ...
}
..and finally example of usage outside the construction loop:
for (size_t iv=0; iv<existing_words.size(); ++iv)
{
correct_word = existing_words[iv];
std::cout << std::get<0>(correct_word) << ": " << std::get<1>(correct_word) << std::endl;
}
std::cout << counter << std::endl;
The same code with a map would look like:
The only declaration would be a map from strings to values (instead of a tuple and vector of tuples),
std::map<std::string, int> existing_words = {};
In the construction loop you would be creating the map pair in a single line like this,
if(word_input.length() == check_integrity)
{
// ...
existing_words[word_input] = getScore(word_input);
// ...
}
While after constructing you would be accessing map elements using .first for the word and .second for the counter. Below is a printing example that also uses a for auto loop:
for (const auto& correct_word : existing_words)
std::cout << correct_word.first << ": " << correct_word.second << std::endl;
std::cout << counter << std::endl;
Notice that maps are by default alphabetically ordered, you can provide your own ordering rules and also use an unordered map if you don't want any ordering/sorting.

Checking for duplicate values associated with key in map?

I'm struggling with outputting unique values of a map<string, vector<string>> I have. Right now, I have a map, and iterate through it, with the goal of outputting only unique values associated with the specified key.
I do need to keep the duplicate values, or else I'd just remove the dups :)
After looking at this post, my set up is like the following:
for( const auto& pair : myMap ){
for( std::size_t i = 0; i < pair.second.size(); ++i ) {
bool notMatch = (pair.second[i] != pair.second[i+1]){
if (pair.first == key && notMatch){
cout << key << " : ";
cout << pair.second[i] << " - at index - " << i << "\n";
}
}
}
I then get an output along the lines of :
"key : value - at index - 6"
"key : value - at index - 10"
My initial thought was that one of the elements might have some extra characters or something, which would make sense as to why the duplicate elements are not being seen as equal.
But when doing a simple check of -
if (pair.second[6] == pair.second[10]){
cout << "They are equal";
} else {
cout << "They are NOT equal";
}
It confirms and returns that the two elements are in fact equal. Since the elements are equal, I'm struggling to understand why bool notMatch = (pair.second[i] != pair.second[i+1]) does not consider them to be equal.
Apologies if this was posted incorrectly, I'll edit if necessary.
Thanks for your help
Building on #Tzalumen's comment, you could insert the values in a set or unordered set and compare the size to the original vector:
for(const auto& pair : myMap){
unordered_set<string> s(pair.second.begin(), pair.second.end());
if (s.size() == pair.second.size()) {
cout << "value has unique elements" << endl;
} else {
cout << "value has duplicate elements" << endl;
}
}
If the set's size is smaller than the vector's size, you know the vector has duplicates.
If you don't want duplicates anywhere, why not have a std::map<std::string, std::set<std::string>> in the first place?

Erase pointer in two maps

I have two maps. The keys of the two maps are the same. The mapped-value of the second one is a pointer, which points to the mapped-value of the first one. When I erase the element in the first map, the pointer in the second map does not vanish automatically. I should first erase the second map and then erase the first one.
// two maps
map<int, int> a;
map<int, int*> pt_a;
int N = 5;
for (size_t i = 0; i < N; i++)
{
a.insert({ i,2 * i });
pt_a.insert({ i,&(a[i]) });
}
// erase the first element of a
a.erase(a.begin());
// after erase
for (auto& i : a) cout << i.first << " " << &(i.second) << endl;
cout << endl;
for (auto& i : pt_a) cout << i.first << " " << i.second << endl;
Is there anything in C++ can simplify this code? If the element in the first map is erased, the corresponding one in the second map is also erased automatically.
If I erase the element in the second map, the memory of pointer is free or not? Should I use std::share_ptr in this case?
Thanks!

how to find the middle element of the map?? STL

Hi I am stuck in between the concept of Map in STL Library/C++.
int arr[] = {10,15,14,13,17,15,16,12,18,10,29,24,35,36};
int n = sizeof arr / sizeof *arr;
map<int, bool> bst;
map<int, bool>::iterator it;
vector<int> median_output;
const int k = 5;
for (int i = 0; i < k; ++i) {
bst.insert(make_pair(arr[i], true));
}
for (it = bst.begin(); it != bst.end(); it++) {
cout << (*it).first << " ";
}
Now when i printed this map, it got printed in sorted Order. Now is there any simplest way to find the middle of this map.....
Need to find the median of a bigger problem... So trying to implement balanced binary search tree..
map is a balanced search tree. To find it's middle - find it's size, and iterate from the begin() for half it's size - that will be the middle. Something like this:
for (it = bst.begin(), int middle = 0; middle < bst.size()/2; it++, middle++) {
cout << (*it).first << " ";
}
// now after the loop it is the median.
If you use map to sort things - then it's an overkill, IMHO. You can do it much more effectively with an array (or vector), and then finding the middle will be trivial as well. map is used for accessing data by key, not just sorting.
With the code shown you are abusing the map to sort the keys.
You can get much more performance, avoiding full sort and copy:
const int len = 14;
const int a[len] = {10,15,14,13,17,15,16,12,18,10,29,24,35,36};
std::nth_element( a, a+len/2, a+len );
std::cout << "Median: " << a[len/2] << std::endl;
If you prefer to use STL containers, your code would look like this (assuming a container with random access iterators):
std::vector<int> v( a, a+len );
std::nth_element( v.begin(), v.begin()+len/2,v.end() );
std::cout << "Median: " << v[len/2] << std::endl;
std::map might not be the best container for locating the median. But this will do the trick pretty simply:
it = bst.begin();
advance( it, bst.size() / 2);
cout << endl << "median: " << it->first << endl;
std::maps can not give you medians in one shot. If you want medians you need to use this algorithm.