I want find the element v[0][0]=1 v[0][1]=2 of the vector v with the use of lambda function and find of stl.
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
vector<vector<int>> v(3);
v[0].resize(2);
v[1].resize(2);
v[2].resize(2);
int n=1, m = 2;
v[0][0]=1; v[0][1]=2;
v[1][0]=0; v[1][1]=0;
v[2][0]=2; v[2][1]=3;
auto it = find(v.begin(), v.end(), [=]( vector<int> vet) {return (vet[0] == n && vet[1] == m);} );
return 0;
}
error: no match for 'operator==' (operand types are 'std::vector'
and 'const main()::)>')|
I don't understand the problem: both vet[0] and n are integer so the operator== should be defined.
I think you meant to use find_if. Moreover the syntax should be changed a bit. Also, m and n are parameters, that the lambda function should receive as parameters. So change your code to this:
auto it = find_if(v.begin(), v.end(), [n, m] (const vector<int>& vet) {return (vet[0] == n && vet[1] == m);} );
Related
I want to be able to accumulate every other pair of elements in a vector using accumulate. I tried the following without much success, returning an error for a non-empty, non-zero vector
return std::accumulate(vec.begin(), vec.end(), 0,
[&](int runningSum, int first, int second)
{return runningSum = runningSum + min(first, second);});
which I now realise probably wouldn't be getting the minimum between pairs. For instance, if I have
vector<int> vec = {1,4,2,3}
I want to return 0 + min(1, 4) + min(2, 3).
On another note, is there any website with many examples of these STL built-ins? I find the examples online far and few. I really want to see the power of accumulate, and get comfortable with it.
std::accumulate() does not allow you to use a predicate with 3 parameters, only 2 parameters - the current running sum, and the current element to be added to that sum. The predicate is called for each individual element and is expected to return the updated sum.
If you want to sum the values in pairs, you can try something like this instead:
vector<int> vec = {1,4,2,3};
...
int *first = nullptr;
return std::accumulate(vec.begin(), vec.end(), 0,
[&](int runningSum, int &value) {
if (first) {
runningSum += std::min(*first, value);
first = nullptr;
} else {
first = &value;
}
return runningSum;
}
);
A better solution would be to simply change your vector to hold a pair of ints (like std::pair<int, int>) as its element type (or at least copy your vector ints to a second vector of pairs), and then you can accumulate the pairs as-is:
vector<pair<int,int>> vec = {{1,4},{2,3}};
...
return std::accumulate(vec.begin(), vec.end(), 0,
[](int runningSum, const pair<int, int> &p) {
return runningSum + std::min(p.first, p.second);
}
);
I think it would be difficult to just use accumulate straight away to sum by min of pairs. You would need to maybe split your existing vector first, then transform them into a vector of the mins, then you could use the accumulate function.
So with that in mind, I would maybe do it like this:
std::vector<int> v{ 1,4,2,3};
std::vector<int> v2;
std::vector<int> v3;
std::vector<int> v4;
std::partition_copy(begin(v),
end(v),
back_inserter(v2),
back_inserter(v3),
[toggle = false](int) mutable { return toggle = !toggle; });
std::transform(begin(v2), end(v2), begin(v3), std::back_inserter(v4), [](auto a, auto b)
{
return std::min(a,b);
});
auto sum_of_min_in_pairs = std::accumulate(begin(v4), end(v4), 0);
Note that the code above will have issues if your vector does not have even amount of elements. Otherwise, transform it into a pair, with some default to match the remainder, depending on what you want to achieve.
With the STL website, cppreference.com is your friend. There are also a few books around I would highly recommend.
Effective STL by Scott Meyers
The C++ standard library by Nicolai Josuttis
I would solve this using std::adjacent_difference and std::accumulate:
#include <algorithm> // std::min
#include <iostream>
#include <numeric> // std::adjacent_difference, std::accumulate
#include <vector>
int main()
{
std::vector v{1, 4, 3, 2, 3, 8, 5, 1};
std::adjacent_difference(
v.cbegin(), v.cend(), v.begin(),
[](auto lhs, auto rhs) { return std::min(lhs, rhs); });
auto is_second_elem{true};
std::cout << std::accumulate(cbegin(v), cend(v), 0,
[&is_second_elem](auto acc, auto min) {
is_second_elem = not is_second_elem;
return is_second_elem ? (acc + min) : acc;
})
<< '\n'; // 7
}
I want to find all tuples in:
vector<tuple<int,int>> tuples; //already sorted
that evaluate the next proposition to "true":
(get<0>(tuple) == val)
I'm trying to use the equal_range function to get a range:
equal_range (tuples.begin(), tuples.end(), val);
How can I express "val" correctly for the value comparison to happen in the first element of the tuples?
You can make a tuple and ignore its last element like this:
#include <tuple>
#include <algorithm>
#include <vector>
#include <functional>
int main()
{
std::vector<std::tuple<int, int>> v = {{1,0}, {2,3}, {4,5}};
const int val = 2;
std::equal_range(v.cbegin(), v.cend(),
std::make_tuple(std::cref(val), 0),
[&val] (const auto& l, const auto& r) {
return std::get<0>(l) < std::get<0>(r);
});
}
Consider the following scenario:
typedef struct myStruct
{
int cn;
std::string dn;
} MyStruct;
int main()
{
std::vector<MyStruct> v;
// fill some data
...
...
int c = 1;
std::vector<MyStruct>::iterator it = std::find_if(v.begin(), v.end(),
[c](const MyStruct& m) -> bool { return m.cn == c; });
// use 'it' to do stuff
}
If v contains MyStruct objects such that the member variable cn has a value c (=1) in more than one entries, how to handle that scenario? As std::find_if() returns an iterator to the first element in the range, what about the rest?
find_if find first element in range and returns iterator to it. For find all you can either write loop, that will search each-time from it:
std::vector<MyStruct>::iterator it = v.begin();
while (it != v.end())
{
it = std::find_if(it, v.end(),
[c](const MyStruct& m) -> bool { return m.cn == c; });
if (it != v.end())
{
// process founded item
++it;
}
}
or you can sort your sequence and use equal_range algorithm, that will return std::pair of iterators.
With the current Standard library, you have to write a either a loop over std::find_if with a predicate (lambda if you can use C++11/14), or use std::copy_if to copy every match to a new sequence.
When the Ranges proposal becomes available (in a Technical Specification along with C++17), things get much easier, e.g. you will be able to write one single chain of composable views and actions:
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>
using namespace ranges;
int main()
{
auto const is_even = [](auto x) { return x % 2 == 0; };
auto const print = [&](auto x) { std::cout << x << ","; return x; };
std::vector<int> v { 1, 11, 42, 57, 63, 72 };
v | view::filter(is_even) | action::transform(print);
}
Live On Coliru (already works with the range-v3 library).
I have overloaded the less than operation for pair<int,int>, so that I can sort a vector in a particular manner. I want it to be in ascending order according to the first key of a pair, and if the first keys are equal, then I'd want it in descending order according to the second key.
The issue is that the sort function doesn't seem to be using the overloaded < operator, but if < is called on 2 pairs, the output returned is what I expect. I have attached a snippet of code below which I'm using for testing:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool operator<(pair<int, int> &a, pair<int, int> &b)
{
if (a.first < b.first) return true;
else if ((a.first == b.first) && (a.second > b.second)) return true;
return false;
}
int main() {
vector<pair<int, int>> test {make_pair(1,10), make_pair(3,4), make_pair(3,8), make_pair(6, 23), make_pair(1,6)};
sort(test.begin(), test.end());
for (int i = 0; i < test.size(); i++)
cout << test[i].first << " - " << test[i].second << " ";
cout << endl;
auto a = make_pair(3,4);
auto b = make_pair(3,8);
cout << (a < b) << endl;
return 0;
}
The input vector is {(1,10), (3,4), (3,8), (6,23), (1,6)}.
I expect the output to be {(1,10), (1,6), (3,8), (3,4), (6,23)}.
Obtained output is {(1,6), (1,10), (3,4), (3,8), (6, 23)}.
As you can see, the obtained output is the one you'd get by using the standard < operator without overloading. So I thought that this might be an issue, and checked (3,4) < (3,8). In this case, the answer was returned as false, in accordance to my overloaded operator. So where am I going wrong? Why isn't sort being affected by the overloaded operator? There are various questions on SO about similar issues, but couldn't find any that helped.
There's already an operator< defined for pairs in the std namespace, and that's the one that's found by the version of std::sort that you are using. Your overload is never found. Use a named predicate instead:
struct MyPairComparator
{
bool operator()(const std::pair<int, int> & a,
const std::pair<int, int> & b) const
{
// ...
}
};
sort(test.begin(), test.end(), MyPairComparator()); // ADL, maybe
// ^^^^^^^^^^^^^^^^^^
Also, the predicate should be callable with constant values, so either take the arguments by value or by const reference.
Note that sort lives in the std namespace. By contrast, when you use the < expression in main, your own overload in the global namespace is indeed found.
It seems you use a C++11 compiler, correct and make it easier using lambda functions. Something like
sort(test.begin(), test.end(), [](const pair<int, int> & a, const pair<int, int> & b) {
if (a.first < b.first) return true;
else if ((a.first == b.first) && (a.second > b.second)) return true;
return false;
});
I have the following code:
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <map>
using namespace std;
struct vals
{
int cods[5];
int sz;
};
struct myComp
{
bool operator()(vals A, vals B) const
{
int i=0;
while(A.cods[i]==B.cods[i] && i<A.sz)
i++;
if(i==A.sz)
return false; //<-----this is the value im changing..
else
return A.cods[i] > B.cods[i];
}
};
map< vals, int, myComp> Mp;
int main()
{
vals g, h;
g.sz=h.sz=3;
g.cods[0] = 12;
g.cods[1] = 22;
g.cods[2] = 32;
Mp.insert(pair< vals, int >(g,4));
Mp.insert(pair< vals, int >(g,7));
cout<<Mp.count(g)<<endl;
cout<<Mp.size()<<endl;
return 0;
}
Now, when declare Mp as map and put false in the binary predicate..
The output is:
1
1
Mp => map && binary predicate:true ==> output: 0 2
Mp => multimap && binary predicate:true ===> output: 0 2
Mp => multimap && binary predicate:false ===> output: 2 2
I thought that the return value of predicate just tells the stl whether to put an element either infront of it or behind it. But I don't get how does this effect the size of the map itself..
Please throw some light on this. Thank you.
Your comparison must implement a strict weak ordering. This requirement is not met when you use
if(i==A.sz)
return true;
in your comparator. In this case, all the elements in the arrays the same. The functor cannot return true if both its arguments are equal. The map cannot function correctly if you do not have a strict weak ordering comparison.
You can greatly simplify your functor by using std::lexicographical_compare:
#include <algorithm> // for std::lexicographical_compare
#include <functional> // for std::greater
...
bool operator()(vals A, vals B) const
{
return std::lexicographical_compare(A, A+A.sz, B, B+B.sz); // less-than
//return std::lexicographical_compare(A, A+A.sz, B, B+B.sz, std::greater<int>()); // gt
}