我有两个列表,其中包含一堆相同类型的元素:
std::list<Part> allParts = step.getSubParts();
std::list<Part> toRemove;
for (Part part : allParts)
{
for (Part partTwo : allParts) {
if (part.getEdges() == partTwo.getEdges())
if (part.getFaces() == partTwo.getFaces())
if (part.getShells() == partTwo.getShells())
if (part.getVertices() == partTwo.getVertices())
if (part.getWires() == partTwo.getWires())
{
part.addAmount(1);
toRemove.push_back(partTwo);
}
}
}
我尝试遍历两者并从中移除,但是我不断遇到list iterators are incompatible
错误。这是我最近的尝试:
std::list<Part>::iterator it;
for (it = step.getSubParts().begin(); it != step.getSubParts().end();)
{
std::list<Part>::iterator i;
for (i = toRemove.begin(); i != toRemove.end();)
{
if (it->getEdges() == i->getEdges())
if (it->getFaces() == i->getFaces())
if (it->getShells() == i->getShells())
if (it->getVertices() == i->getVertices())
if (it->getWires() == i->getWires())
{
it = step.getSubParts().erase(it);
}
else
{
it++;
}
i++;
}
}
我尝试的所有方法均无效。正确的方法是什么?
答案 0 :(得分:2)
您应该考虑使用remove_if
或erase_if
而不是自己擦除,以免使iterator
在循环中无效。
顺便说一句,您应该这样写谓词:
if (it->getEdges() == i->getEdges() &&
it->getFaces() == i->getFaces() &&
it->getShells() == i->getShells() &&
it->getVertices() == i->getVertices() &&
it->getWires() == i->getWires()) {
// do something
}
您的代码使人们(至少对我)难以理解您的目的。
答案 1 :(得分:1)
首先,遵循不要重复自己的原则并编写比较函数以供将来使用是一个好主意:
auto compare_parts = [](const Part& p1, const Part& p2) -> bool {
return ( (p1.getEdges() == p2.getEdges())
and (p1.getFaces() == p2.getFaces())
and (p1.getShells() == p2.getShells())
and (p1.getVertices() == p2.getVertices())
and (p1.getWires() == p2.getWires()) );
}
您将使用它重写第一个循环,然后看它看起来有多简单。
那么为什么不使用c ++内置方法使用我们编写的函数从列表中删除元素呢?这使用了c ++中称为binding parameters的新功能,可以在这里为我们提供帮助
#include <functional>
using namespace std::placeholders;
for (auto&& badPart : toRemove) {
auto isBad = std::bind(compare_parts, badPart, _1);
step.getSubParts().remove_if(isBad);
}
这就是从列表中删除特殊条目的方式。
答案 2 :(得分:0)
我认为最干净的方法是:
Part
您可以将其放在类的内部或外部,如果将其实现为外部函数,则看起来像这样
inline bool operator==(const Part& lhs, const Part& rhs) {
return lhs.getEdges() == rhs.getEdges() &&
lhs.getFaces() == rhs.getFaces() &&
lhs.getShells() == rhs.getShells() &&
lhs.getVertices() == rhs.getVertices() &&
lhs.getWires() == rhs.getWires();
}
这只是一种实现方式
if (allParts.size() > 1) {
for(auto partIt = std::begin(allParts); partIt != std::end(allParts); partIt++) {
for(auto partIt2 = std::next(partIt); partIt2 != std::end(allParts);) { // Manual increasing because we erase stuff
if(*partIt == *partIt2) { // Previously implemented equility operator
partIt->AddAmount(1);
partIt2 = allParts.erase(partIt2); // If erase, use the returned iterator as your next `Part`
} else {
partIt2++; // Only increment if nothing was erased (when you erase iterators get invalidated)
}
}
}
}