I've got two vectors:
struct MyData{
double value;
};
std::vector<int> remove_flags = {0, 1, 0, 0, 0, 0, 1, 0};
std::vector<MyData> data = {{},{},{},{},{},{},{},{}};
The remove_flags
vector contains an array of flags of the exact same size as data
, each flag is either 0, or 1, where 1 means the data should be removed.
I would like to use remove_flags
to remove elements from data
in place, ie performing the erase remove idiom, but erasing based on values in remove_flags
. The end result should be data
with elements erased, and hopefully remove_flags
with those same elements erased.
Doing this manually is annoying, and I wanted to use Range-v3 for this. I'm currently using C++17.
After looking through the documentation, I don't think I've found a solution, the closest thing I could come up with is:
auto result = ranges::views::zip(remove_flags, data) | ranges::actions::remove_if([](std::pair<const int&, const MyData&> pair){
return pair.first != 0;
});
remove_flags.erase(result.first, remove_flags.end());
data.erase(result.second, data.end());
But actions cannot operate on the view zip, so this does not compile. If I switch ranges::actions::remove_if
to ranges::views::remove_if
a strange views object is returned, presumably one that has not actually performed the std::remove
equivalent operation on the two vectors.
I could use contaner_to
but that would involve a copy, and I don't want to pay that kind of unnecessary penalty for convenience. I've seen what I want accomplished in boost where actual zip pair iterators can be used to return two separate removal results.
Is this kind of pattern possible in Range-v3?
std::vector
of the results? Isn't a view enough? – Pyrogenousresult.first
andresult.second
– Nannettenannidata
andremove_flags
, so I think it's fair to presume you want to use those afterward, i.e. those twostd::vector
s contain the "output/result/effect" you want to achieve. That's where you "mention" in your post that you want the result of the code to be in astd::vector
(result, notresult
, just as in my previous comment). However, let's put it in another way: your example is not a minimal reproducible example; can you either make it one or describe in words what the desired outcome/result/effect of the code is? – PyrogenousMyData
represents Dear ImGUI table row items. Because ImGUI is immediate mode, in order to remove elements from the UI, I must first mark elements some how (ie selection) then remove them afterwards, as displaying rows is literally a for loop that runs each time. Again, it's UI is immediate mode, selection doesn't persist with out me creating an array that maintains the selection (effectivelyremove_flags
). Removing these elements removes the UI rows. These rows also represent markers, removing theMyData
then also removes the markers (which is desired). – Nannettenannifor (auto x : result)
orfor (auto it = result.begin(); it != result.end(); ++it)
, then a view would be fine. – Pyrogenousif(ImGui::BeginTable()){ ...; clipped.Begin(data.size()); for(int row_n = clipped.Start; row_n < clipped.End; ++i){ auto& my_data = data[row_n]; if(ImGui::Selectable("",remove_flags[row_n],...){...};if(ImGui::DisplayColumn(0)){ ImGui::InputText("input", &(my_data.name))}; if(ImGui::DisplayColumn(1)){...}}ImGui::EndTable();}
The loop is not trivial, I need references to mydata inside the loop itself, I use the values of my_data inside the loop itself, need to modify it from within the generated UI. – Nannettenanni