I have a 2D vector that i have to check if a ID already have been defined. The struct look like this
struct ExchangeStruct1 {
std::vector<int16_t>id;
std::vector< ObjectType_enum>type;
std::vector<void*>source;
std::vector<void*>destination;
ExchangeStruct1();
};
The vector is defined as following
std::vector<std::vector<ExchangeStruct1>> exchangeList;
Is it possebile to search for the id in the second level of the vector. I tried using
it = std::find_if(exchangeList.begin(), exchangeList.end(), [key](const ExchangeStruct1>& o) -> bool {return o.id == key; });
But it only search in the first level
CodePudding user response:
With ranges::join_view
this becomes trivial:
auto jv = exchangeList | std::ranges::views::join;
auto it = std::ranges::find_if(jv, [key](const ExchangeStruct1& o) {
return o.id == key;
});
if (it != jv.end())
{
// ...
}
CodePudding user response:
If you only need to know if the id
is present or not you can nest calls to std::find_if
:
#include <vector>
#include <algorithm>
#include <iostream>
struct foo {
int id;
};
int main() {
std::vector<std::vector<foo>> exchangeList{ {{0},{1},{2}},{{3},{4}}};
int target = 2;
bool found =
std::find_if(exchangeList.begin(),exchangeList.end(),
[target](const auto& a){
return std::find_if(a.begin(),a.end(),[target](const auto& f){
return f.id == target;
}) != a.end();
}) != exchangeList.end();
std::cout << found;
}
However, this is a case where a handwritten nested loop is definitely more readable:
bool find_id(const auto& exchangeList,int id) {
for (const auto& row : exchangeList) {
for (const auto& element : row) {
if (element.id == id) return true;
}
}
return false;
}
This is also simpler to modify in case you do need an iterator to the found element. You'd just need to be careful to choose a sentinel to return when the element was not found. It cannot be exchangeList.end()
, but you could return a std::pair< iterator to outer vector, iterator to inner vector>
and return { exchangeList.end(), whatever }
when no element was found.