Reputation: 484
Suppose I have a vector A = {1 0 1 1 0 0 0 1 0}
. Now I want to get the indexes of all occurrences of 0 returned as another vector B
.
template< class InputIt, class T>
std::vector<int> IndicesOf(InputIt first, InputIt last, const T& value) {
}
Here is a start:
std::vector<int>::iterator iter = std::find_if(A.begin(), A.end(), 0);
B = std::distance(A.begin(), iter);
Upvotes: 23
Views: 25341
Reputation: 28500
This solution is a bit longer if you consider #include
s and using
s, but that is irrelevant in bigger code bases.
Without those, and considering that one could store some useful function object like first
and second
in a header, the core part becomes a one liner:
auto result = enumerate(v) | filter(second_is_zero) | transform(first);
Defining second_is_zero
is a bit overkill; defining auto constexpr equal_to = std::equal_to<>{};
instead, would lead to the following, which is still readable, once you get used to functional utilities such as compose
and partial
:
auto result = enumerate(v) | filter(compose(partial(equal_to, 0), second))
| transform(first);
Here's the complete code, though
#include <boost/hana/functional/compose.hpp>
#include <boost/hana/functional/partial.hpp>
#include <functional>
#include <iostream>
#include <vector>
#include <range/v3/view/enumerate.hpp>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/transform.hpp>
using boost::hana::compose;
using boost::hana::partial;
using namespace ranges::views;
int main()
{
std::vector<int> v{1,0,1,1,0,0,0,1,0};
// define some useful function object
auto constexpr first = [](auto const& pair){ return pair.first; };
auto constexpr second = [](auto const& pair){ return pair.second; };
auto constexpr second_is_zero = compose(partial(std::equal_to<>{},0), second);
// oneline to get the result (it's in a view, not a vector)
auto result = enumerate(v) // attach indexes 0,1,2,... to the elements
| filter(second_is_zero) // filter based on second
| transform(first); // extract the indexes
// the following prints 14568
for (auto i : result) {
std::cout << i;
}
std::cout << std::endl;
}
Upvotes: 1
Reputation: 1243
To the answer of @some-programmer-dude with lamda:
#include <algorithm> //find_if
std::vector<int> A{1, 0, 1, 1, 0, 0, 0, 1, 0};
std::vector<int> B;
std::vector<int>::iterator it = A.begin();
while ((it = std::find_if(it, A.end(), [](int x){return x == 0; })) != A.end())
{
B.push_back(std::distance(A.begin(), it));
it++;
}
Upvotes: 5
Reputation: 409442
Just call std::find_if
again, with the previously returned iterator (plus one) as the beginning. Do in a loop until std::find_if
returns A.end()
.
Sample code
#include <algorithm> //find_if
bool isZero(int x){
return x == 0;
}
std::vector<int>::iterator iter = A.begin();
while ((iter = std::find_if(iter, A.end(), isZero)) != A.end())
{
// Do something with iter
iter++;
}
Upvotes: 29
Reputation: 126
Try this: char c: element whose indexes you want to get. I used a string but this same code will work perfectly fine with a vector. vecky stores all the indexes found.
std::vector<int> getIndex(string s, char c)
{
std::vector<int> vecky;
for (int i = 0; i != s.length(); i++)
{
if (s[i] == c)
{
vecky.push_back(i);
}
}
return vecky;
}
Upvotes: 2