Using find with vector<pair<int, int>> - c++

I ran into the following problem: suppose I have
pair<int, int> p(1,2)
vector<pair<int, int>> vec;
I want to use find to get the iterator pointing to the element p in the vector
find(vec.begin(), vec.end(), p)
But it gave me the error
type 'std::__1::pair<int, int>' does not provide a call operator
How should I proceed?

This is what I've used and it's worked great.
#include <iostream>
#include <vector>
#include <algorithm>
struct FindPair {
FindPair (int first, int second)
: m_first_value(first)
, m_second_value(second) { }
int m_first_value;
int m_second_value;
bool operator()
( const std::pair<int, int> &p ) {
return (p.first == m_first_value && p.second == m_second_value);
}
};
int main()
{
std::vector< std::pair<int, int> > myVec;
std::vector< std::pair<int, int> >::iterator it;
myVec.push_back(std::make_pair(1,1));
myVec.push_back(std::make_pair(1,2));
it = std::find_if(myVec.begin(), myVec.end(), FindPair(1, 2));
if (it != myVec.end())
{
// We Found it
std::cout << "Matched Found on Current Iterator!" << std::endl;
std::cout << "it.first: " << (*it).first << std::endl;
std::cout << "it.second: " << (*it).second << std::endl;
}
else
{
std::cout << "Nothing Matched!" << std::endl;
}
return 0;
}
Output:
Matched Found on Current Iterator!
it.first: 1
it.second: 2

Related

Problem with inserting vector elements into map?

While putting sorted vector elements into map, it inserts them in ascending order after it has been sorted in descending order with the compare function. I know that map is in ascending order by default based on its key, but I am not sure why it sorts them again in ascending order based on its value. Is this common in std::map<std::string, int>?
I simply want to return a map in descending order by its value, I need to display the directory strings with a number of items found by decreasing order.
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
bool compare_dir(std::pair<std::string, int>&a,
std::pair<std::string, int>&b)
{
return a.second > b.second;
}
void sort_func(std::map<std::string, int>& M)
{
std::map<std::string, int>::iterator itr;
std::vector<std::pair<std::string, int>> temp;
std::map<std::string, int> result;
for(auto &it : M)
temp.push_back(it);
sort(temp.begin(), temp.end(), compare_dir);
for(auto &el : temp)
std::cout << el.first << " " << el.second << std::endl;
std::cout << std::endl;
for(auto & el : temp)
result.insert(el);
for(itr = result.begin(); itr != result.end(); itr++)
std::cout << itr->first << " " << itr->second << std::endl;
}
int main()
{
std::map<std::string, int> my_map{{"dir1", 1}, {"dir2", 2}, {"dir3", 3}};
for (const auto& [key, value] : my_map) {
std::cout << '[' << key << "] = " << value << "; " << std::endl;
}
std::cout << std::endl;
sort_func(my_map);
}

Understanding priority_queue by problem : Find K Closest Elements Solution

I was solving one problem on leetcode problem - Find K Closest Elements.
Here is my IDE code : ide.geeksforgeeks
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
std::vector<int> findClosestElements(std::vector<int>& arr, int k, int x)
{
std::vector<int> res;
// min heap
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>,
std::greater<std::pair<int, int>>> pq;
std::cout << "Debug queue : \n";
for (auto it : arr)
{
int closest = abs(it - x);
pq.push(std::make_pair(closest, it));
//std::cout << closest << " : " << it << "\n";
if (pq.size() > k)
{
pq.pop();
}
}
std::cout << "\nIterating queue : \n";
while(!pq.empty())
{
res.push_back(pq.top().second);
std::cout << pq.top().first << " : " << pq.top().second << "\n";
pq.pop();
}
std::sort(res.begin(), res.end());
return res;
}
int main()
{
std::vector<int> arr = {1,2,3,4,5};
auto res = findClosestElements(arr, 4, 3);
return 0;
}
While I was iterating the queue, I can not see the minimum number : 0 : 3 which should be the top element of priority_queue. Can anyone please suggest?
Max heaps solves the problem.
vector<int> findClosestElements(vector<int>& arr, int k, int x)
{
std::vector<int> res;
std::priority_queue<std::pair<int, int>> pq;
for (auto it : arr)
{
int closest = abs(it - x);
//std::cout << closest << " : " << it << "\n";
pq.push(std::make_pair(closest, it));
if (pq.size() > k)
{
pq.pop();
}
}
//std::cout << "\nDebug queue : \n";
while(!pq.empty())
{
res.push_back(pq.top().second);
//std::cout << pq.top().first << " : " << pq.top().second << "\n";
pq.pop();
}
std::sort(res.begin(), res.end());
return res;
}

How to read a map of <string,vector<pair<int, string>>>

I am having a map like this
typedef vector< pair<int, string> > Categories;
map<string,Categories> cats;
but when I am trying to read elements of the map like
for(map<string,Categories>::const_iterator it = cats.begin(); it != cats.end(); ++it)
{
std::cout << it->first << " " << it->second.first<<"\n";
}
I do get errors
error: 'const class std::vector<std::pair<int, std::basic_string<char>
' has no member named 'first' std::cout << it->first << " " << it-> second.first<<"\n";
error: 'const class std::vector ' has no member named 'first'
std::cout << it->first << " " << it->second.first<<"\n";
Its clear as Crystal, that you might have many elements in your values of your map, which is a std::vector< std::pair<int, std::string>>
Then how would you print elements of a vector? The options are:
random access (i.e, vec[index])
iterator (i.e, std::vector< std::pair<int, std::string>>::const_iterator itr;)
or by a range based for loop (i.e, for(const auto& it: vec) )
In your case, if you wanna have something simple and easy code is using a range based loop:
for(const auto& it: cats)
{
std::cout << it.first << " = "; // keys
for(const auto& ve: it.second) // values vec
std::cout << ve.first << "-" << ve.second << "\t";
std::cout << std::endl;
}
If you still wanna have long iterator loops, here is it.
see live action here: https://www.ideone.com/3bS1kR
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <iterator>
typedef std::vector< std::pair<int, std::string>> Categories;
int main()
{
std::map<std::string, Categories> cats;
cats["key1"] = {std::make_pair(1, "pair1"), std::make_pair(1, "pair2"), std::make_pair(1, "par3")};
cats["key2"] = {std::make_pair(2, "pair1"), std::make_pair(2, "pair2")};
cats["key3"] = {std::make_pair(3, "pair1")};
std::cout << "Range based loop \n";
for(const auto& it: cats)
{
std::cout << it.first << " = "; // keys
for(const auto& ve: it.second) // values vec
std::cout << ve.first << "-" << ve.second << "\t";
std::cout << std::endl;
}
std::cout << "\nIterator loop \n";
std::map<std::string, Categories>::const_iterator it;
std::vector< std::pair<int, std::string>>::const_iterator curr_val_it;
for(it = cats.cbegin(); it != cats.cend(); ++it)
{
std::cout << it->first << " = "; // keys
for(curr_val_it = it->second.cbegin(); curr_val_it != it->second.cend(); ++curr_val_it )
std::cout << curr_val_it->first << "-" << curr_val_it->second << "\t"; // values vec
std::cout << std::endl;
}
return 0;
}
you need to access a element of the vector first, then the pair within.
... it->second[0].first<< ...
better impl of loop:
for(const auto& cat : cats)
{
string mapidx = cat.first;
vector<pair<int, std::string>> catvect = cat.second;
}
then you can have a seperate loop to read the contents of the vector:
for(const auto& cat : cats)
{
string mapidx = cat.first;
vector<pair<int, std::string>> catvect = cat.second;
for (const auto& entry : catvect)
{
int number = entry.first;
string whatever = entry.second;
}
}
the temp variables are just for readability, no need for all the copies ;)
Error is exacly what compiler told you:
const class std::vector ' has no member named 'first'
so, you have do decide how to print your map by overloading ostream opeartor, below example how it can be achived:
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>
typedef std::vector<std::pair<int, std::string>> Categories;
std::map<std::string,Categories> cats;
std::ostream& operator << (std::ostream& os, const std::vector<std::pair<int, std::string>>& v)
{
os << "[";
for (auto& el : v) {
os << " " << el.first << " : " << el.second;
}
os << "]";
return os;
}
int main() {
cats.emplace("cat1", std::vector<std::pair<int, std::string>>(1, std::make_pair(1, "category1")));
for(auto& cat : cats) {
std::cout << cat.first << " " << cat.second << "\n";
}
}
Since we are storing Vector Categories inside a Map we will have to iterate Vector too:
for(map<string,Categories>::const_iterator it = cats.begin(); it != cats.end(); ++it)
{
//iterator for vector (it->second)
for(Categories::const_iterator it2 = it->second.begin(); it2 != it->second.end(); it2++ )
{
std::cout << it->first << " " << it2->first<<" "<<it2->second <<"\n";
}
}

How to delete elements by key in map, which contains char and pair<int,string>

I want to delete all elements which pair first == 0
Here code:
int main()
{
map<char, pair<int,string>> myMap;
map<char, pair<int,string>>::const_iterator it;
for (int i = 0; i < 10; i++)
{
char c = 'a' + i;
pair<int,string> p = make_pair(rand() % 2, "dd");
myMap.insert(make_pair(c,p));
}
it = find_if(myMap.begin, myMap.end(), isEqual);
}
bool isEqual(const pair<char, pair<int, string> > element)
{
return element.second.first == 0;
}
Error:
/usr/include/c++/4.8/bits/stl_algo.h:150: error: could not convert
'__first.std::_Rb_tree_iterator<_Tp>::operator*<std::pair<const char,
std::pair<int, std::basic_string<char> > > >()' from 'std::pair<const
char, std::pair<int, std::basic_string<char> > >' to 'std::pair<int,
std::basic_string<char> >'
while (__first != __last && !bool(__pred(*__first)))
Yes, of course.
I think I'd write the code something like this (I've added a bit of extra code to print out the contents of the map before and after the deletion to show that it worked):
#include <map>
#include <utility>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
ostream &operator<<(ostream &os, pair<int, string> const &p) {
return os << "[" << p.first << ", " << p.second << "]";
}
int main() {
map<char, pair<int, string>> myMap;
for (int i = 0; i < 10; i++) {
char c = 'a' + i;
pair<int, string> p = make_pair(rand() % 2, "dd");
myMap.insert(make_pair(c, p));
}
std::cout << "before:\n";
for (auto const &p : myMap)
std::cout << p.first << ": " << p.second << "\n";
map<char, pair<int, string> >::iterator it;
while (myMap.end() != (it = find_if(myMap.begin(), myMap.end(), [](auto p) { return p.second.first == 0; })))
myMap.erase(it);
std::cout << "\nafter\n\n";
for (auto const &p : myMap)
std::cout << p.first << ": " << p.second << "\n";
}
I would do this with a simple loop. You need to remember to keep track of the iterator when you erase an element from the map:
#include <map>
#include <ctime>
#include <string>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
int main()
{
std::srand(std::time(0));
std::map<char, std::pair<int, std::string>> myMap;
for(int i = 0; i < 10; i++)
{
char c = 'a' + i;
auto p = std::make_pair(rand() % 2, "dd");
myMap.insert(std::make_pair(c, p));
}
std::cout << "\nbefore:\n";
for(auto const& p: myMap)
{
std::cout << p.first;
std::cout << " {" << p.second.first;
std::cout << ", " << p.second.second;
std::cout << "}" << '\n';
}
// remove items in a simple loop
for(auto iter = myMap.begin(); iter != myMap.end();)
{
if(iter->second.first == 0)
iter = myMap.erase(iter); // grab new iterator when erasing
else
++iter; // otherwise just increment
}
std::cout << "\nafter:\n";
for(auto const& p: myMap)
{
std::cout << p.first;
std::cout << " {" << p.second.first;
std::cout << ", " << p.second.second;
std::cout << "}" << '\n';
}
}
Example Output:
before:
a {0, dd}
b {1, dd}
c {0, dd}
d {0, dd}
e {1, dd}
f {0, dd}
g {0, dd}
h {1, dd}
i {0, dd}
j {0, dd}
after:
b {1, dd}
e {1, dd}
h {1, dd}

C++ most frequent element in map

I made a program that takes data from file, puts it into vector and then checks for most frequent element in the vector. (using map)
The problem is when I have same number of elements in the data (two Element1, two Element2, one Element3). It returns Element1 and I need it to pass the information that there is "no most frequent element".
My code looks like:
using namespace std;
bool comp(const pair<string, unsigned long> &pair1,
const pair<string, unsigned long> &pair2) {
return pair1.second < pair2.second;
}
string Odczyt::tokenizer() {
inFile.open("baza.txt");
while (!inFile.eof()) {
for (int i = 0; i < 4; i++) {
inFile >> row1[i] >> row2[i] >> row3[i] >> row4[i];
}
}
sVector1.assign(row1, row1 + 3);
string w1 = most_occurred(sVector1);
return w1;
}
string Odczyt::most_occurred(vector<string> &vec) {
map<string, unsigned long> str_map1;
for (vector<string>::const_iterator it = vec.begin(); it != vec.end();
++it) {
++str_map1[*it];
}
return max_element(str_map1.begin(), str_map1.end(), comp)->first;
}
Create a variable which stores the number of times you have found an element which occurs m times (where m is the current maximum number of times any element has occurred). If at the termination point of the algorithm you have more than one element appearing m times, then you know there is no single most-frequently-occurring element.
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
string most_occurred(vector<string> &vec) {
map<string, unsigned long> str_map1;
std::string max_element = "";
int max_count = 0;
typedef vector<string>::const_iterator iter;
iter end = vec.end();
for (iter it = vec.begin(); it != end; ++it) {
int count = ++str_map1[*it];
if(count == max_count) max_element = "no max found";
if(count > max_count) {
max_count = count;
max_element = *it;
}
}
return max_element;
}
int main() {
std::string arr1[5] = {"aa" , "bb", "cc", "dd", "ee"}; // no max found
std::string arr2[5] = {"aa" , "aa", "cc", "dd", "ee"};// aa
std::string arr3[5] = {"aa" , "aa", "cc", "cc", "ee"}; // no max found
std::vector<std::string> input1(arr1, arr1+5);
std::vector<std::string> input2(arr2, arr2+5);
std::vector<std::string> input3(arr3, arr3+5);
std::cout << most_occurred(input1) << std::endl;
std::cout << most_occurred(input2) << std::endl;
std::cout << most_occurred(input3) << std::endl;
}
the result is:
no max found
aa
no max found
The following test resulted in no max found.
int main() {
std::string arr1[24] = {"Element1", "Element2", "Element33", "1",
"Element1", "Element2", "Element33", "2", "Element11", "Element2",
"Element33", "2", "Element11" "Element21" "Element31", "2", "Element11",
"Element21", "Element31", "1", "Element12", "Element21", "Element31",
"1"}; // no max found
std::vector<std::string> input1(arr1, arr1+24);
std::cout << most_occurred(input1) << std::endl;
}
If the above code returns std::string("") then there was no max element, else it will return the max.
This is a frequent operation here is my sample code:
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <iterator>
using namespace std;
int main(int argc, char* argv[]) {
// number -> frequency
map<int, int> idfreq = {{1, 3}, {2, 10}, {3,8}, {9, 15}, {7,30}};
vector<pair<int, int> > v;
copy(idfreq.begin(), idfreq.end(), back_inserter(v));
for (auto& el : v) {
cout << el.first << " " << el.second << endl;
}
cout << endl;
make_heap(v.begin(), v.end(), [](const pair<int,int> &a, const pair<int,int> &b){ return a.second < b.second; });
// with -std=c++14
//make_heap(v.begin(), v.end(), [](auto& a, auto& b){ return a.second < b.second; });
cout << v.front().first << " " << v.front().second << " most frequent element\n";
cout << "after make heap call\n";
for (auto& el : v) {
cout << el.first << " " << el.second << endl;
}
cout << endl;
return 0;
}