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
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);
}
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;
}
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";
}
}
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}
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;
}