Printing a `vector<pair<int, int>>` - c++

Here is my code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
vector<pair<int, int>> v;
v.push_back({ 1, 5 });
v.push_back({ 2,3 });
v.push_back({ 1,2 });
sort(v.begin(), v.end());
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
}
I'm getting an error C2679 binary "=": no operator found which takes a right-hand operand of type "std::pair<int, int>" (or there is no acceptable conversion). I have no idea what this means, or why copy doesn't print. Without copy, there is no error, but I want to print out vector v. Is there some other way to do htis?

In your code, you're trying to print std::pair<int, int> using a function printing one int, that's not going to work.
Since std::ostream doesn't have an overload taking std::pair by default, you have to provide an overload for the operator<< taking the type std::pair<int, int> yourself:
// This is necessary because ADL doesn't work here since
// the std::ostream_iterator will be looking for the overload
// in the std namespace.
struct IntPair : std::pair<int, int> {
using std::pair<int, int>::pair;
};
std::ostream& operator<<(std::ostream& o, const IntPair& p) {
o << p.first << " " << p.second;
return o;
}
int main() {
std::vector<IntPair> v;
v.push_back({ 1, 5 });
v.push_back({ 2, 3 });
v.push_back({ 1, 2 });
std::sort(v.begin(), v.end());
std::copy(v.begin(), v.end(), std::ostream_iterator<IntPair>(std::cout, " "));
}

After you sort you can use a for-each loop to iterate over the vector container and print the pairs:
for(const pair<int,int>& x: v)
{
cout << x.first << " " << x.second << "\n";
}

There's no standard way to cout a std::pair because there is no stream insertion (<<) operator overload for it. You could instead use std::for_each:
std::for_each(
v.begin(),
v.end(),
[](const auto& p) { std::cout << p.first << "," << p.second << std::endl; });

In my opinion this is the fastest way what I know
template<typename T, typename Y>
auto operator<<(std::ostream& os, const std::vector<std::pair<T,Y>>& pair) -> std::ostream&
{
for(const auto& el : pair)
os << el.first << ' ' << el.second << '\n';
return os;
}

Related

what is the time complexity and space complexity of this solution? Question- Top K Frequent Elements (Leetcode-Medium)

vector<int> topKFrequent(vector<int>& nums, int k) {
if(k==nums.size())
return nums;
map<int,int> mp;
for(int i=0;i<nums.size();i++)
mp[nums[i]]++;
multimap<int,int> m;
for(auto& it:mp){
m.insert({it.second,it.first});
}
vector<int> ans;
for (auto itr = m.crbegin(); itr != m.crend(); ++itr){
ans.push_back(itr->second);
if(ans.size()==k)
break;
}
return ans;
}
I am using multimap to sort the map by values.I don't understand if I use priority queue which time complexity is better ? using priority_queue or using multimap? Can anyone explain?
In my opinion you have not the optimal solution.
You use a std::map instead of a std::unordered_map. That will have a higher complexity in most cases. std::maphas logarithmic complexity, std::unordered_map has on average constant-time complexity.
The std::multimap is not needed at all. It will add unneccessary space and time complexity (Logarithmic). A std::priority_queuehas constant time lookup, but logarithmic insertion. So, could be better than the std::multimapin your case.
The most efficient solution would be to use a std::unordered_map and then std::partial_sort_copy. The complexity for this is O(N·log(min(D,N)), where N = std::distance(first, last), D = std::distance(d_first, d_last) applications of cmp. (Taken from CPPReference).
A somehow generic C++17 example solution could be the below:
#include <iostream>
#include <utility>
#include <unordered_map>
#include <algorithm>
#include <vector>
#include <iterator>
#include <type_traits>
// Helper for type trait We want to identify an iterable container ----------------------------------------------------
template <typename Container>
auto isIterableHelper(int) -> decltype (
std::begin(std::declval<Container&>()) != std::end(std::declval<Container&>()), // begin/end and operator !=
++std::declval<decltype(std::begin(std::declval<Container&>()))&>(), // operator ++
void(*std::begin(std::declval<Container&>())), // operator*
void(), // Handle potential operator ,
std::true_type{});
template <typename T>
std::false_type isIterableHelper(...);
// The type trait -----------------------------------------------------------------------------------------------------
template <typename Container>
using is_iterable = decltype(isIterableHelper<Container>(0));
// Some Alias names for later easier reading --------------------------------------------------------------------------
template <typename Container>
using ValueType = std::decay_t<decltype(*std::begin(std::declval<Container&>()))>;
template <typename Container>
using Pair = std::pair<ValueType<Container>, size_t>;
template <typename Container>
using Counter = std::unordered_map<ValueType<Container>, size_t>;
// Function to get the k most frequent elements used in any Container ------------------------------------------------
template <class Container>
auto topKFrequent(const Container& data, size_t k) {
if constexpr (is_iterable<Container>::value) {
// Count all occurences of data
Counter<Container> counter{};
for (const auto& d : data) counter[d]++;
// For storing the top k
std::vector<Pair<Container>> top(k);
// Get top k
std::partial_sort_copy(counter.begin(), counter.end(), top.begin(), top.end(),
[](const Pair<Container>& p1, const Pair<Container>& p2) { return p1.second > p2.second; });
return top;
}
else
return data;
}
int main() {
std::vector testVector{ 1,2,2,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,6,7 };
for (const auto& p : topKFrequent(testVector, 2)) std::cout << "Value: " << p.first << " \t Count: " << p.second << '\n';
std::cout << '\n';
double cStyleArray[] = { 1.1, 2.2, 2.2, 3.3, 3.3, 3.3 };
for (const auto& p : topKFrequent(cStyleArray, 2)) std::cout << "Value: " << p.first << " \t Count: " << p.second << '\n';
std::cout << '\n';
std::string s{ "abbcccddddeeeeeffffffggggggg" };
for (const auto& p : topKFrequent(s, 2)) std::cout << "Value: " << p.first << " \t Count: " << p.second << '\n';
std::cout << '\n';
double value = 12.34;
std::cout << topKFrequent(value, 2) << "\n";
}

How to print vector<int> to terminal in c++ [duplicate]

This question already has answers here:
How do I print out the contents of a vector?
(31 answers)
Closed 4 years ago.
I am trying to print a vector of integers to the terminal using "cout", but I get an error message during compiling:
no match for 'operator<<' (operand types are 'std::basic_ostream' and 'std::vector')
cout << "Disparity at points: " << disparityVector << endl;
The snippet of code looks like this:
vector<int> disparityVector;
for ( int i=0; i<drawPixels.size(); i++) // Get disparity at each point of the drawn line
disparityVector.push_back((int)disparityMapOutput.at<int16_t>(pos[i].y, pos[i].x));
cout << "Disparity at points: " << disparityVector << endl;
There is no error with assigning the values to the vector, only the "cout" part of the code is making errors
For example, using ostream_iterator.
Sample from that page:
// ostream_iterator example
#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <vector> // std::vector
#include <algorithm> // std::copy
int main () {
std::vector<int> myvector;
for (int i=1; i<10; ++i) myvector.push_back(i*10);
std::ostream_iterator<int> out_it (std::cout,", ");
std::copy ( myvector.begin(), myvector.end(), out_it );
return 0;
}
You'll need something like below, if you want to do it the way you've coded it.
template<class T>
inline std::ostream& operator<< (std::ostream& o, std::vector<T> const& v) {
for (auto const& i : v)
o << i << " ";
return o;
}
std::ostream& operator<<(std::ostream& os, const vector<int>& v)
{
std::ostream_iterator<int> _oit(cout, " ");
std::copy(v.begin(), v.end(), _oit);
return os;
}
This error means that vector<T> has no operator<< implementation.
You need to iterate over your vector and print each element:
for(int i = 0; i < disparityVector.size; i++) {
cout << disparityVector[i];
}
cout << endl;

C++ display map that has vector

std::map<std::string, std::vector<string>> data;
In order to print out this by using copy, how should my std::ostream_iterator be?
Apparently std::ostream_iterator<std::pair<std::string, std::vector<std::string>>> out_it(std::cout, "\n"); did not make it.
My operator<< overload is the following std::ostream& operator<<(std::ostream& out, const std::pair<std::string, std::vector<std::string>>& p) and it writes out the p.first and p.second and returns it.
If you do any serious programming in C++, you will eventually need a generic way to print out collections.
Here is the basis of one:
#include <iostream>
#include <map>
#include <vector>
#include <string>
// introduce the concept of an object that emits values to an ostream
// by default it simply calls operator <<
template<class T> struct emitter
{
using arg_type = T;
emitter(const T& v) : v_(v) {}
friend std::ostream& operator<<(std::ostream& os, const emitter& e) {
return os << e.v_;
}
const T& v_;
};
// introduce the concept of an io manipulator called emit
template<class T> auto emit(const T& v) -> emitter<T>
{
return emitter<std::decay_t<T>>(v);
}
// specialise the emitter for maps
template<class K, class V, class C, class A>
struct emitter<std::map<K, V, C, A>>
{
using arg_type = std::map<K, V, C, A>;
emitter(const arg_type& v) : v_(v) {}
friend std::ostream& operator<<(std::ostream& os, const emitter& e) {
const char* elem_sep = "\n\t";
const char* end_sep = " ";
os << "{";
for (const auto& elem : e.v_)
{
os << elem_sep << emit(elem.first) << ": " << emit(elem.second);
end_sep = "\n";
}
return os << end_sep << "}";
}
const arg_type& v_;
};
// specialise the emitter for vectors
template<class V, class A>
struct emitter<std::vector<V, A>>
{
using arg_type = std::vector<V, A>;
emitter(const arg_type& v) : v_(v) {}
friend std::ostream& operator<<(std::ostream& os, const emitter& e) {
const char* elem_sep = " ";
const char* end_sep = " ";
os << "[";
for (const auto& elem : e.v_)
{
os << elem_sep << emit(elem);
elem_sep = ", ";
}
return os << end_sep << "]";
}
const arg_type& v_;
};
int main() {
// build test data
std::map<std::string, std::vector<std::string>> data;
data.emplace("a", std::vector<std::string>{ "now", "is", "the", "time" });
data.emplace("b", std::vector<std::string>{ "for", "all", "good", "men" });
data.emplace("c", std::vector<std::string>{ "to", "come", "to", "the" });
data.emplace("d", std::vector<std::string>{ "aid", "of", "their", "party" });
// request an emitter manipulator
std::cout << emit(data) << std::endl;
}
Expected output:
{
a: [ now, is, the, time ]
b: [ for, all, good, men ]
c: [ to, come, to, the ]
d: [ aid, of, their, party ]
}
So here is a operator<< that will print out the contents of one pair from your map:
std::ostream& operator<<(std::ostream& out, const std::pair<std::string, std::vector<std::string>>& p) {
out << p.first << ": "; // prints the string from key
for (const auto& i : p.second) // loops throught the whole vector that is asociated with that key
out << i << ", ";
return out;
}
So to use it in this example. If you ennter this into your map:
std::map<std::string, std::vector<string>> data;
std::vector<std::string> vec = {"VAL1", "VAL2", "VAL3"};
data.insert(std::make_pair("KEY", vec));
auto it = data.find("KEY");
std::cout << *it;
This would be what wil get printed out using the operator<< above:
KEY: VAL1, VAL2, VAL3,
You can also change the formatting a bit so the comma isn't after the last value as well but that's only a cosmetic problem. Your problem was in that you wanted to print vector while it doesn't have std operator<<. So in order to print vector you must manually loop through it's content like in my example with the ranged for.
To custom print your vector, you'd have to write some code yourself. To make sure your custom operator is used, I suggest you use std::stringstream to turn your key-value pair into a string, which you'd then feed into an std::ostream_iterator<std::string>.
Something, like this (pardon the using namespace std;):
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <sstream>
#include <map>
using namespace std;
int main() {
map<string, vector<string>> m {
{"a", {"1", "2"}},
{"b", {"1", "2"}},
{"b", {"1", "2"}},
};
transform(begin(m), end(m), ostream_iterator<string>(cout), [](auto& p){
stringstream ss;
ss << p.first << ", {";
bool first = true;
for (auto& s : p.second)
{
ss << (first ? "" : ", ") << s;
first = false;
}
ss << "}\n";
return ss.str();
});
return 0;
}
I didn't actually write the operator<<, but you can substitue yours to make the lambda body short);

How to use tolower with lambda function in map? C++

I want to change all the words stored in a map to lower case. with lambda function and transform, how should I do that?
std::map <string, int> M;
std::map<string, int> M1;
std::transform(M.begin(), M.end(), M1.begin(),
[](pair<const string, int> const & p) { ::tolower(p.first); });
You can't edit keys in a map, so you'll have to create a new map
Something along the lines of:
iterate over the values in your map
take a copy of the key
transform it to lowercase
insert it into your result map:
Example:
#include <iostream>
#include <map>
#include <algorithm>
int main()
{
std::map<std::string, int> map = {{ "HELLO", 1 }, { "WORLD", 2 }};
std::cout << "before:\n";
for (auto& kv : map)
{
std::cout << '\t' << kv.first << ":" << kv.second << '\n';
}
// create a new map with lowercase keys
std::map<std::string, int> out;
std::for_each(map.begin(), map.end(), [&](auto& kv)
{
std::string lower;
std::transform(kv.first.begin(), kv.first.end(), std::back_inserter(lower), tolower);
out[lower] = kv.second;
});
std::cout << "after:\n";
for (auto& kv : out)
{
std::cout << '\t' << kv.first << ":" << kv.second << '\n';
}
return 0;
}
output:
before:
HELLO:1
WORLD:2
after:
hello:1
world:2
std::transformassigns the result of the functor to elements in the destination range. This means that the destination iterator must be the start of range with same size as the input range. In your example, the destination is an empty map. The transform essentially is the following loop:
std::map <string, int> M;
std::map<string, int> M1;
for(auto i=M.begin(), j=M1.begin(); i != M.end(); ++i,++j)
{
*j = f(*i);
}
Decrementing j is illegal for empty containers, and doesn't really make sense for a map since you cannot change the key.
What you can see from this code is that your lambda is also incorrect. It should transform one (key value) pair into an object of the target type. In your case, the target type is the same.
You either have to resize the destination container before, e.g. by calling resize if it was a vector, or use an iterator which adapts the assignment to map::insert. The STL provides adaptors for this:
#include <map>
#include <string>
#include <cctype>
#include <iterator>
#include <algorithm>
int main() {
std::map <std::string, int> M;
std::map<std::string, int> M1;
std::transform(M.begin(), M.end(), std::inserter(M1, M1.begin()),
[](std::pair<const std::string, int> const & p)
{
std::string lowercase;
std::transform( p.first.begin(), p.first.end(),
std::back_inserter(lowercase),
[](auto c) {return std::tolower(c);} );
return std::make_pair(lowercase, p.second);
});
return 0;
}
If you want to use exactly std::transform then you can use the following approach
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <cctype>
#include <iterator>
#include <utility>
int main ()
{
std::map<std::string, int> m1 = { { "FIRST", 1 }, { "SECOND", 2 } };
for ( const auto &p : m1 )
{
std::cout << p.first << '\t' << p.second << std::endl;
}
auto to_lower_case = []( const std::pair<const std::string, int> &p )
{
std::string t; t.reserve( p.first.size() );
std::transform( p.first.begin(), p.first.end(),
std::back_inserter( t ), ::tolower );
return std::make_pair( t, p.second );
};
std::cout << std::endl;
std::map<std::string, int> m2;
std::transform( m1.begin(), m1.end(),
std::inserter( m2, m2.begin() ), to_lower_case );
for ( const auto &p : m2 )
{
std::cout << p.first << '\t' << p.second << std::endl;
}
}
The program output is
FIRST 1
SECOND 2
first 1
second 2
In the program there are used std::transform two times.

Sort a vector using its elements

i need to know how can we sort a vector of user define class using its elements.
Say i have a class called "coordinates" with getX and getY method that return an int value.
I have created and array of vector "vector PointTwoD vcP2D(5);"
class coordinates {
int getX();
int getY();
)
Now the issue,
1) I need to sort the vector "vcP2D" using getX() and sort in asc order
2) Say an user enters the "2" as the x coordinate. And using that info i need to find which vector contains 2
Please advice
This will do:
std::sort(v.begin(), v.end(), [](const coordinates& c, const coordinates& d){ return c.getX() < d.getX(); });
It uses a C++11 Lambda expression as a binary predicate for std::sort.
A short demonstration:
#include <algorithm>
#include <vector>
#include <iostream>
struct coordinates
{
int x;
int y;
};
int main()
{
std::vector<coordinates> v{ {2,3}, {0,0}, {1,5} };
std::sort(v.begin(), v.end(), [](const coordinates& c, const coordinates& d) { return c.x < d.x; });
std::cout << "sorted by x values, values of \"x\": " << v[0].x << " " << v[1].x << " " << v[2].x << "\n";
std::sort(v.begin(), v.end(), [](const coordinates& c, const coordinates& d) { return c.y < d.y; });
std::cout << "sorted by y values, values of \"x\": " << v[0].x << " " << v[1].x << " " << v[2].x << "\n";
}
A demo of how to find an element in the same way:
#include <algorithm>
#include <vector>
#include <iostream>
struct coordinates
{
int x;
int y;
};
int main()
{
std::vector<coordinates> v{ {2,3}, {0,0}, {1,5} };
auto result = std::find_if(v.begin(), v.end(), [](const coordinates& c){ return c.x == 1 && c.y == 5; });
if(result != v.end())
std::cout << "point (1,5) is number " << std::distance(v.begin(), result)+1 << " in the vector.\n";
else
std::cout << "point (1,5) not found.\n";
}
If you are looking to search in the sorted vector, you can use std::binary_search which takes a comparison function (the same as std::sort above). It also does not give an iterator to that element, only a true or false.
You need to define a strict weak order on your elements, either using operator< () or a binary predicate, and then use std::sort().
The easiest approach is to create a less than operator<():
bool operator< (coordinates const& c0, coordinates const& c1) {
// return a suitable result of comparing c0 and c1 such that operator<()
// become a strict weak order
}
With this all you need to do to sort a std::vector<coordinates> is to use std::sort(). To locate a specific object you would use std::lower_bound().