我有一个std::set
,我需要删除相似的相邻元素:
DnaSet::const_iterator next = dna_list.begin();
DnaSet::const_iterator actual = next;
++next;
while(next != dna_list.end()) // cycle over pairs, dna_list is the set
{
if (similar(*actual, *next))
{
Dna dna_temp(*actual); // copy constructor
dna_list.erase(actual); // erase the old one
do
{
dna_temp.mutate(); // change dna_temp
} while(!dna_list.insert(dna_temp).second); // insert dna_temp
}
++actual;
++next;
}
有时程序无法退出主循环。我认为当我删除dna_list
中的最后一个元素时会出现问题。执行此任务的正确方法是什么?
答案 0 :(得分:5)
使用actual = next
而不是++actual
。
删除actual
后,它是一个无效的迭代器,因此++actual
会表现得很奇怪。 next
应保持不变,因此将actual
分配给next
应该有效。
答案 1 :(得分:2)
您最好的选择是创建一个使用similar()
谓词的比较函子。然后你需要做的就是用比较仿函数构造集合,你就完成了。集合本身将看到两个相似的元素相同,只会让第一个元素出现。
struct lt_different {
bool operator()(int a, int b) {
return a < b && !similar(a, b);
}
private:
bool similar(int a, int b)
{
// TODO:when are two elements similar?
const int EPSILON = 2;
return abs(a - b) < EPSILON;
}
};
// ...
set<int> o; // fill this set with your data
// copy your data to a new set that rejects similar elements
set<int,lt_different> s(o.begin(), o.end(), lt_different());
您可以使用set s
:插入元素,删除元素,修改元素 - 集合本身将确保集合中不存在两个相似的元素。
也就是说,你也可以自己编写一个算法,如果只是为了另一种选择。从std::adjacent_find()
查看<algorithm>
。它会发现第一次出现两个连续的相同元素;坚持这个立场。找到它后,从该点找到与这些元素不同的第一个元素。最终得到两个迭代器,表示一系列连续的类似元素。您可以使用set的erase()
方法删除它们,因为它有一个需要两个迭代器的重载。
泡沫,冲洗,重复整套。