C++ Compare first and second element for all pairs in container - c++

I have vector of pair like this:
std::vector < std::pair < int /*Val1*/, int /*Val2*/ > > myVector;
What is the efficient way to compare for each pair in 'myVector' first and second element of pair (Val1 and Val2) are same or not.
The only way I could think of is -
bool IsFirstAndSecondSame(vector<pair<T, T>> myVector)
{
for(auto valuePair : myVector)
{
if(valuePair.first != valuePair.second)
return false'
}
return true;
}
Although in example I have used pair of integers, the question is about any pair having first and second element of same type.

Although in example I have used pair of integers, the question is about any pair having first and second element of same type.
You're probably asking about using a templated function like this:
template<typename T>
bool IsFirstAndSecondSame(const vector<pair<T, T>>& myVector) // const
// ^^^^^
// makes no sense
// with free functions
{
for(const auto& valuePair : myVector)
{
if(valuePair.first != valuePair.second)
return false'
}
return true;
}

Related

Is it possible to iterate through a vector of vectors columnwise?

I have a vector of vectors of strings. I want to find the lengths of the longest string in each column. All the subvectors are of the same length and have an element stored in it, so it would be rather easy to find it with two for loops and reversed indices.
vector<vector<string>> myvec = {
{ "a", "aaa", "aa"},
{"bb", "b", "bbbb"},
{"cc", "cc", "ccc"}
};
But is it possible to do it with iterators without using indices?
Assuming the inner vectors are all the same length, you can have something like
template <typename T>
class columnwise {
std::vector<std::vector<T>> * underlying;
struct proxy {
std::vector<std::vector<T>> * underlying;
std::vector<T>::difference_type offset;
struct iterator {
std::vector<std::vector<T>>::iterator outer;
std::vector<T>::difference_type offset;
using reference = typename std::vector<T>::reference;
using pointer = typename std::vector<T>::pointer;
iterator operator++() { ++outer; return *this; }
reference operator*() { return *(outer->begin() + offset); }
pointer operator->() { return (outer->begin() + offset).operator->(); }
bool operator==(iterator rhs) { return (outer == rhs.outer) && (offset == rhs.offset); }
};
public:
iterator begin() { return { underlying->begin(), offset }; }
iterator end() { return { underlying->end(), offset }; }
};
struct iterator {
// member type aliases
std::vector<std::vector<T>> * underlying;
std::vector<T>::difference_type offset;
iterator operator++() { ++offset; return *this; }
proxy operator*() { return { underlying, offset }; }
bool operator==(iterator rhs) { return (underlying== rhs.underlying) && (offset == rhs.offset); }
};
std::vector<T>::difference_type inner_size() { if (auto it = underlying->begin(); it != underlying->end()) { return it->size(); } return 0; }
public:
columnwise(std::vector<std::vector<T>> & vec) : underlying(&vec) {}
iterator begin() { return { underlying, 0 }; }
iterator end() { return { underlying, inner_size() }; }
};
Which iterates as you expect.
What about something like this?
std::vector<std::size_t> max_lengths(myvec.front().size(), 0);
for (auto const& strings : myvec) {
std::transform(max_lengths.begin(), max_lengths.end(), strings.begin(), max_lengths.begin(),
[](std::size_t l, std::string const& s) {
return std::max(l, s.size());
}
);
}
Demo
Here is a solution using C++20 ranges and lambdas that is similar to Nelfeals answer:
// returns a function returning the i-th element of an iterable container
auto ith_element = [](size_t i) {
return [i](auto const& v){
return v[i];
};
};
// returns a range over the i-th column
auto column = [ith_element](size_t i) {
return std::views::transform(ith_element(i)); // returns a range containing only the i-th elements of the elements in the input range
};
// returns the size of something
auto length = [](auto const& s){ return s.size(); };
// returns the max length of the i-th column
auto max_length_of_col = [column, length](auto const& v, size_t i) {
return std::ranges::max(
v | column(i) | std::views::transform(length)
);
};
I personally like how the ranges library helps you convey intent with your code, rather than having to prescribe the procedure to achieve your goal.
Note that if you replace the body of inner lambda in ith_element with the following block, it will also work for iterable containers without random access.
auto it = v.cbegin();
std::ranges::advance(it, i);
return *it
Demo
As a final remark, this solution lets you iterate over one column given an index of the column. I would advise against implementing a column iterator for vector<vector>: The existence of an iterator implies that something exists in memory that you can iterate over. The existence of columns is only implied by the additional information that you have given us, namely that all rows have the same length. If you do want iterators both for columns and rows, I would wrap your container in a new type (usually called matrix or similar) that properly conveys that intent. Then you can implement iterators for that new type, see Calath's answer.
EDIT:
I realized that my argument against a column iterator can be used as an argument against the column function in this answer as well. So here is a solution that let's you iterate over columns in a range-based for loop intead of iterating over column indices:
for (auto column : columns(myvec)){
std::cout << max_length(column) << std::endl;
}

c++ std Copying a list to map

Consider the following:
struct A
{
int i;
double d;
std::string s;
};
std::list<A> list_A;
I'd like to copy all the elements of list_A to a map such that every pair in the map will consist of an element from list_A as value and its string s as key. Is there a way of doing it that is more elegant than looping through the list and insert each element along with its string as key to the map?
I love standard library algorithms and lambdas but it doesn't get much simpler than:
for (const A& value : list_A) {
map_A.insert(std::make_pair(value.s, value));
}
The other methods are doing the equivalent of this code and this loop is readable and just as fast.
This should get you the idea of how to use transform:
std::pair<std::string, A> pairify(const A& a) { return std::make_pair(a.s, a); }
std::transform(list.begin(), list.end(), std::inserter(map, map.end()), pairify);
The reason to use the inserter is:
An insert interator is a special type of output iterator designed to allow algorithms that usually overwrite elements (such as copy) to instead insert new elements automatically at a specific position in the container.
Sorry answered too quickly last time without details, here is a compilable code.
struct A
{
int i;
double d;
std::string s;
};
std::list<A> list_A;
std::pair<std::string, A> convert(const A &x) {
return make_pair(x.s,x);
}
int main() {
std::map<std::string,A> out;
std::transform(list_A.begin(), list_A.end(), std::inserter(out,out.end()),convert);
}
I may store it in a set: in this way there would not be data duplication in the map (s itself):
struct A
{
bool operator < (const A& r_) const { return (s < r_.s); }
int i;
double d;
std::string s;
};
std::list<A> list_A;
std::set<A> set_A;
for ( std::list<A>::const_iterator itr = list_A.begin(); itr != list_A.end(); ++itr ) {
if ( ! set_A.insert(*itr).second ) {
// Handle duplicated elements
}
}
I may keep the loop: in this way you could handle duplicated elements correctly.
If you use C++11 you can use lambda function with capture:
std::map<std::string, A> m;
std::list<A> l;
std::for_each(l.begin(), l.end(),
[&](const A& a) {
m.insert(std::make_pair(a.s, a));
});

C++ set search for pair element?

So I have a set of pairs<string ,string>
And I want to use find() to search for a single string which would be in the "first" of the pair, then if I find that string in first I want to return second from that function.
My current attempt is..
myList::iterator i;
i = theList.find(make_pair(realName, "*"));
return i->second;
Is C++11 acceptable?
auto it = find_if(theList.begin(), theList.end(),
[&](const pair<string, string>& val) -> bool {
return val.first == realName;
});
return it->second;
Or in C++03, first define a functor:
struct MatchFirst
{
MatchFirst(const string& realName) : realName(realName) {}
bool operator()(const pair<string, string>& val) {
return val.first == realName;
}
const string& realName;
};
then call it like so:
myList::iterator it = find_if(a.begin(), a.end(), MatchFirst(realName));
return it->second;
This will only return the first match, but from your question, it looks like that's all you're expecting.
You can use std::set<std::pair<std::string, std::string> > for this but you will need a custom
comparison object for this because the pair's relational operator takes both elements for this. That said, it seems as if you actually should use a std::map<std::string, std::string> instead.
The definition of < for std::pair implements a lexicographical order and "" is the minimum element for strings. Combining this we get:
typedef std::pair<std::string, std::string> StringPair;
typedef std::set<StringPair> Set;
std::string const* find_first(Set const& s, std::string const& key) {
Set::const_iterator const it = s.lower_bound(std::make_pair(key, ""));
// Check that it actually points to a valid element whose key is of interest.
if (it == s.end() or it->first != key) { return 0; }
// Yata!
return &it->second;
}
The trick is using lower_bound appropriately.
Returns an iterator pointing to the first element which does not compare less than value.
If it returns end(), then it did not find anything interesting.
Otherwise, it->first >= key so we get rid of the > case (of no interest to us)
I would point out though that this only returns the first element of the range. If you are interested in all elements, try:
typedef std::pair<Set::const_iterator, Set::const_iterator> SetItPair;
SetItPair equal_range_first(Set const& s, std::string const& key) {
StringPair const p = std::make_pair(key, "");
return std::make_pair(s.lower_bound(p), s.upper_bound(p));
}
This will return the full range of nodes in s whose first element is equal to key. You then just have to iterate over this range:
for (Set::const_iterator it = range.first; it != range.second; ++it) {
// do something
}
And you don't even have to worry whether the return of lower_bound or upper_bound was end or not.
if lower_bound returns end(), then so does upper_bound, and the loop is skipped
if lower_bound points to a node for which it->first > key, then upper_bound will point to that same node, and the loop is skipped
That is the power of ranges: no need to make special checks, the ranges just end up empty when there is no match, and so the loop over them... is skipped in a single check.

std::map find_if condition style confusion

I'd like to use std::find_if to search for the first element in my map that has a certain value in a specific element of its value structure. I'm a little confused though. I think I need to use bind1st or bind2nd, but I'm not positive that's the right way to go.
Here's some pseudo-code:
struct ValueType { int x, int y, int z };
std::map<int, ValueType> myMap;
... {populate map}
std::map<int, ValueType>::iterator pos = std::find_if(myMap.begin(), myMap.end(), <?>);
So, let's say that I wanted to find the first element of the map where the .x member of the ValueType was equal to a certain integer value (which can change each call).
What would be the best way to write a function or function object to achieve this? I understand that the <?> has to be a unary predicate which makes me think I'll need bind1st or bind2nd to provide the integer value I'm checking for, but I'm not sure how to go about it. It's been way too long since I looked at this stuff! >.<
You can use a lambda function
int val = ...;
auto it = std::find_if(myMap.begin(), myMap.end(),
[val](const std::pair<int, ValueType> & t) -> bool {
return t.second.x == val;
}
);
But as Kirill V. Lyadvinsky answer suggests the "first" element may not be what you expect.
Elements in the map are not sorted by value, they are sorted according to the key. So the phrase "the first element" has not much sense.
To find some element (not the first) that has x equal to some value you can write the functor as follows:
struct check_x
{
check_x( int x ) : x_(x) {}
bool operator()( const std::pair<int, ValueType>& v ) const
{
return v.second.x == x_;
}
private:
int x_;
};
Then use it as follows:
// find any element where x equal to 10
std::find_if( myMap.begin(), myMap.end(), check_x(10) );
For the lazy, use a C++17 auto lambda, then you don't need to be verbose with the type.
const auto it = std::find_if(myMap.begin(), myMap.end(), [&val](const auto &it) {
return it.second.x == val; // Comparing with the object
}
);
Building on all the answers above I cheat by using decltype with C++11 semantics.
auto beg_ = myMap.begin();
auto end_ = myMap.end();
auto it = find_if(beg_, end_,
[&some_val](decltype(*beg_) & vt) {
return vt.second == some_val;});
if (end_ != it) {
auto key_found = (*it).first;
} else {
// throw error not found.
}
struct Pred
{
Pred(int x) : x_(x) { }
bool operator()(const std::pair<int, ValueType>& p)
{
return (x_ == p.second.x);
}
private:
int x_;
};
... = std::find_if(myMap.begin(), myMap.end(), Pred(NUMBER));
This doesn't have anything to do with std::bind1st or std::bind2nd. First of all, you have to keep in mind that the elements of a map are key-value pairs, in your case std::pair<int,ValueType>. Then you just need a predicate that compares the x member of the second member of yuch a pair against a specific value:
struct XEquals : std::unary_function<std::pair<int,ValueType>,bool>
{
XEquals(int _x)
: x(_x) {}
bool operator()(const std::pair<int,ValueType> &v) const
{ return p.second.x == x; }
int x;
};
If you want to search also in values then may be better to use Boost Bimap in order not to be slow?
using Boost.Bind and Boost.Lambda:
...
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
...
typedef std::map<int, ValueType> MapType;
...
MapType::iterator pos = std::find_if(myMap.begin(), myMap.end(),
boost::bind(&ValueType::y, boost::bind(&MapType::iterator::value_type::second, _1)) == magic_number);

Erase-remove idiom for deleting in a nested container? (deleting outer ones; C++ STL)

when i'm deleting from a non-nested container like a vector, i'm doing something like:
struct is_to_remove
{
is_to_remove(dynamic_bitset<>& x) : x(x) {}
const bool operator()(unsigned int id)
{
return x[id];
}
private:
dynamic_bitset<> x;
};
inline static void remove_elements_in_vector(vector<unsigned int>& vec, boost::dynamic_bitset<>& to_remove)
{
// use the erase-remove idiom to remove all elements marked in bitset
vec.erase( remove_if(vec.begin(), vec.end(), is_to_remove(to_remove)), vec.end() );
}
That is the so called erase-remove idiom.
Now, i have a second data strucurevector<vector<unsigned int> > or deque<vector<unsigned int> >, where i want to delete the outer container elements (which is itself a container of the inner type) according to a bitset.
Is it possible to use the erase-remove idiom on this nested container types?
If it is, how is it possible?
Are there restrictions? (like: vec of vec is possible, but not deque of vec)?
My first and naive approach was the following. I assumed that remove_if is iterating sequentially and in order over the elements and deciding one after the other. Is that a wrong assumption?
struct is_to_remove_new
{
is_to_remove_new(dynamic_bitset<>& x, unsigned int index) : x(x), index(index) {}
const bool operator()(vector<unsigned int> & vec)
{
return x[index++];
}
private:
dynamic_bitset<> x;
unsigned int index;
};
inline static void remove_elements_in_vectorvector(vector<vector<unsigned int> >& vec, boost::dynamic_bitset<>& to_remove)
{
// use the erase-remove idiom to remove all elements marked in bitset
vec.erase( remove_if(vec.begin(), vec.end(), is_to_remove_new(to_remove, 0)), vec.end() );
}
The result is wrong, therefore i'm looking for a correct solution here. I suppose i assumed some things, which aren't guaranteed. For me, the base question is the following: How to get the identity of the inner container for checking if it is to remove..
My naive approach posted above just counts and assumes a sequential processing.
Thanks for your help.
Sascha
Update and Warning
For a vector o vectors, Stas solution is working great. But i think this solution will not work for a deque of vectors because a deque isn't saved in a contiguous way. This means, that the calculation of the index in the functor fails.
Can anyone verify that?
It doesn't matter which elements are in the vector. If you define which of them should be removed, they will be removed.
As you said, the question is how to identify an element in a vector. The most obvious answer is by its index [0; vector_size - 1].
Thanks to a vector, you can easily get an element index, by the element itself.
std::vector<std::string> vec;
vec.push_back("zero");
vec.push_back("one");
vec.push_back("two");
std::string& elem = vec[2];
int index = std::distance(&vec[0], &elem); // get element index by element itself
// index == 2
So, you can easily identify vector elements by indices inside remove_if algorithm predicate. Take a look at the following example. It is pretty silly and use hard-coded std::bitset<6>, but this is just an illustration:
#include <vector>
#include <string>
#include <bitset>
struct ToRemove
{
ToRemove(std::vector<std::string>& vec, const std::string& mask)
: m_vec(vec)
, m_mask(mask)
{}
bool operator()(std::string& obj)
{
const int index = std::distance(&m_vec[0], &obj);
return m_mask[index];
}
std::vector<std::string>& m_vec;
std::bitset<6> m_mask;
};
Usage
int main (int argc, char const *argv[])
{
std::vector<std::string> vec;
vec.push_back("zero");
vec.push_back("one");
vec.push_back("two");
vec.push_back("three");
vec.push_back("four");
vec.push_back("five");
std::string mask = ("010011"); // Remove "zero", "one" and "four"
vec.erase(remove_if(vec.begin(), vec.end(), ToRemove(vec, mask)), vec.end());
for (unsigned i = 0; i < vec.size(); ++i)
{
std::cout << vec[i] << " ";
}
std::cout << std::endl;
return 0;
}
Result
two three five